lemon/lgf_writer.h
author Alpar Juttner <alpar@cs.elte.hu>
Mon, 15 Oct 2018 23:39:22 +0200
changeset 1172 d7e25df22e88
parent 1076 97d978243703
permissions -rw-r--r--
Fix warnings emitted by g++ 7.3.1 (#614)
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@1092
     5
 * Copyright (C) 2003-2013
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) {}
alpar@1092
   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@487
   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
  ///
alpar@1076
   947
  /// \brief Return a \ref lemon::DigraphWriter "DigraphWriter" class
kpeter@487
   948
  ///
alpar@1076
   949
  /// This function just returns a \ref lemon::DigraphWriter
alpar@1076
   950
  /// "DigraphWriter" class.
deba@598
   951
  ///
deba@598
   952
  /// With this function a digraph can be write to a file or output
deba@598
   953
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
   954
  /// attributes. For example, with the following code a network flow
deba@598
   955
  /// problem can be written to the standard output, i.e. a digraph
deba@598
   956
  /// with a \e capacity map on the arcs and \e source and \e target
deba@598
   957
  /// nodes:
deba@598
   958
  ///
deba@598
   959
  ///\code
deba@598
   960
  ///ListDigraph digraph;
deba@598
   961
  ///ListDigraph::ArcMap<int> cap(digraph);
deba@598
   962
  ///ListDigraph::Node src, trg;
deba@598
   963
  ///  // Setting the capacity map and source and target nodes
deba@598
   964
  ///digraphWriter(digraph, std::cout).
deba@598
   965
  ///  arcMap("capacity", cap).
deba@598
   966
  ///  node("source", src).
deba@598
   967
  ///  node("target", trg).
deba@598
   968
  ///  run();
deba@598
   969
  ///\endcode
deba@598
   970
  ///
alpar@1076
   971
  /// For a complete documentation, please see the
alpar@1076
   972
  /// \ref lemon::DigraphWriter "DigraphWriter"
deba@598
   973
  /// class documentation.
alpar@1076
   974
  /// \warning Don't forget to put the \ref lemon::DigraphWriter::run() "run()"
deba@598
   975
  /// to the end of the parameter list.
kpeter@487
   976
  /// \relates DigraphWriter
deba@598
   977
  /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
deba@598
   978
  /// \sa digraphWriter(const TDGR& digraph, const char* fn)
deba@598
   979
  template <typename TDGR>
deba@598
   980
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
deba@598
   981
    DigraphWriter<TDGR> tmp(digraph, os);
kpeter@487
   982
    return tmp;
kpeter@487
   983
  }
kpeter@487
   984
kpeter@487
   985
  /// \brief Return a \ref DigraphWriter class
kpeter@487
   986
  ///
kpeter@487
   987
  /// This function just returns a \ref DigraphWriter class.
kpeter@487
   988
  /// \relates DigraphWriter
deba@598
   989
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
   990
  template <typename TDGR>
alpar@877
   991
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@598
   992
                                    const std::string& fn) {
deba@598
   993
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@487
   994
    return tmp;
kpeter@487
   995
  }
kpeter@487
   996
kpeter@487
   997
  /// \brief Return a \ref DigraphWriter class
kpeter@487
   998
  ///
kpeter@487
   999
  /// This function just returns a \ref DigraphWriter class.
kpeter@487
  1000
  /// \relates DigraphWriter
deba@598
  1001
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@598
  1002
  template <typename TDGR>
deba@598
  1003
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
deba@598
  1004
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@487
  1005
    return tmp;
kpeter@487
  1006
  }
kpeter@487
  1007
deba@598
  1008
  template <typename GR>
ladanyi@303
  1009
  class GraphWriter;
ladanyi@303
  1010
deba@598
  1011
  template <typename TGR>
deba@598
  1012
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
deba@598
  1013
  template <typename TGR>
deba@598
  1014
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
deba@598
  1015
  template <typename TGR>
deba@598
  1016
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
deba@165
  1017
deba@165
  1018
  /// \ingroup lemon_io
alpar@209
  1019
  ///
deba@1024
  1020
  /// \brief \ref lgf-format "LGF" writer for undirected graphs
deba@165
  1021
  ///
deba@165
  1022
  /// This utility writes an \ref lgf-format "LGF" file.
kpeter@192
  1023
  ///
kpeter@192
  1024
  /// It can be used almost the same way as \c DigraphWriter.
kpeter@192
  1025
  /// The only difference is that this class can handle edges and
kpeter@192
  1026
  /// edge maps as well as arcs and arc maps.
deba@201
  1027
  ///
deba@201
  1028
  /// The arc maps are written into the file as two columns, the
deba@201
  1029
  /// caption of the columns are the name of the map prefixed with \c
deba@201
  1030
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
deba@201
  1031
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
deba@201
  1032
  /// of the arc) and the label of corresponding edge.
kpeter@559
  1033
  template <typename GR>
deba@165
  1034
  class GraphWriter {
deba@165
  1035
  public:
deba@165
  1036
kpeter@559
  1037
    typedef GR Graph;
deba@598
  1038
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1039
deba@165
  1040
  private:
deba@165
  1041
deba@165
  1042
deba@165
  1043
    std::ostream* _os;
deba@165
  1044
    bool local_os;
deba@165
  1045
deba@598
  1046
    const GR& _graph;
deba@165
  1047
deba@165
  1048
    std::string _nodes_caption;
deba@165
  1049
    std::string _edges_caption;
deba@165
  1050
    std::string _attributes_caption;
alpar@209
  1051
deba@165
  1052
    typedef std::map<Node, std::string> NodeIndex;
deba@165
  1053
    NodeIndex _node_index;
deba@165
  1054
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
  1055
    EdgeIndex _edge_index;
deba@165
  1056
alpar@209
  1057
    typedef std::vector<std::pair<std::string,
alpar@209
  1058
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
  1059
    NodeMaps _node_maps;
deba@165
  1060
alpar@209
  1061
    typedef std::vector<std::pair<std::string,
deba@165
  1062
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
  1063
    EdgeMaps _edge_maps;
deba@165
  1064
alpar@209
  1065
    typedef std::vector<std::pair<std::string,
deba@165
  1066
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
  1067
    Attributes _attributes;
deba@165
  1068
deba@165
  1069
    bool _skip_nodes;
deba@165
  1070
    bool _skip_edges;
deba@165
  1071
deba@165
  1072
  public:
deba@165
  1073
deba@165
  1074
    /// \brief Constructor
deba@165
  1075
    ///
deba@1024
  1076
    /// Construct an undirected graph writer, which writes to the
deba@1024
  1077
    /// given output stream.
deba@598
  1078
    GraphWriter(const GR& graph, std::ostream& os = std::cout)
kpeter@293
  1079
      : _os(&os), local_os(false), _graph(graph),
alpar@209
  1080
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1081
deba@165
  1082
    /// \brief Constructor
deba@165
  1083
    ///
deba@1024
  1084
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1085
    /// output file.
deba@598
  1086
    GraphWriter(const GR& graph, const std::string& fn)
deba@165
  1087
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@290
  1088
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1089
      if (!(*_os)) {
deba@295
  1090
        delete _os;
deba@295
  1091
        throw IoError("Cannot write file", fn);
deba@295
  1092
      }
deba@290
  1093
    }
deba@165
  1094
deba@165
  1095
    /// \brief Constructor
deba@165
  1096
    ///
deba@1024
  1097
    /// Construct a undirected graph writer, which writes to the given
deba@165
  1098
    /// output file.
deba@598
  1099
    GraphWriter(const GR& graph, const char* fn)
deba@165
  1100
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@290
  1101
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1102
      if (!(*_os)) {
deba@295
  1103
        delete _os;
deba@295
  1104
        throw IoError("Cannot write file", fn);
deba@295
  1105
      }
deba@290
  1106
    }
deba@165
  1107
deba@165
  1108
    /// \brief Destructor
deba@165
  1109
    ~GraphWriter() {
alpar@209
  1110
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1111
           it != _node_maps.end(); ++it) {
alpar@209
  1112
        delete it->second;
deba@165
  1113
      }
deba@165
  1114
alpar@209
  1115
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1116
           it != _edge_maps.end(); ++it) {
alpar@209
  1117
        delete it->second;
deba@165
  1118
      }
deba@165
  1119
alpar@209
  1120
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1121
           it != _attributes.end(); ++it) {
alpar@209
  1122
        delete it->second;
deba@165
  1123
      }
deba@165
  1124
deba@165
  1125
      if (local_os) {
alpar@209
  1126
        delete _os;
deba@165
  1127
      }
deba@165
  1128
    }
alpar@209
  1129
deba@190
  1130
  private:
deba@165
  1131
deba@598
  1132
    template <typename TGR>
deba@598
  1133
    friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
deba@598
  1134
    template <typename TGR>
alpar@877
  1135
    friend GraphWriter<TGR> graphWriter(const TGR& graph,
deba@598
  1136
                                        const std::string& fn);
deba@598
  1137
    template <typename TGR>
deba@598
  1138
    friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
alpar@877
  1139
alpar@209
  1140
    GraphWriter(GraphWriter& other)
deba@190
  1141
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
alpar@209
  1142
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1143
deba@190
  1144
      other._os = 0;
deba@190
  1145
      other.local_os = false;
deba@190
  1146
deba@190
  1147
      _node_index.swap(other._node_index);
deba@190
  1148
      _edge_index.swap(other._edge_index);
deba@190
  1149
deba@190
  1150
      _node_maps.swap(other._node_maps);
deba@190
  1151
      _edge_maps.swap(other._edge_maps);
deba@190
  1152
      _attributes.swap(other._attributes);
deba@190
  1153
deba@190
  1154
      _nodes_caption = other._nodes_caption;
deba@190
  1155
      _edges_caption = other._edges_caption;
deba@190
  1156
      _attributes_caption = other._attributes_caption;
deba@190
  1157
    }
deba@190
  1158
deba@165
  1159
    GraphWriter& operator=(const GraphWriter&);
deba@165
  1160
deba@165
  1161
  public:
deba@165
  1162
kpeter@584
  1163
    /// \name Writing Rules
deba@165
  1164
    /// @{
alpar@209
  1165
kpeter@192
  1166
    /// \brief Node map writing rule
deba@165
  1167
    ///
kpeter@192
  1168
    /// Add a node map writing rule to the writer.
deba@165
  1169
    template <typename Map>
deba@165
  1170
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
  1171
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1172
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1173
        new _writer_bits::MapStorage<Node, Map>(map);
deba@165
  1174
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1175
      return *this;
deba@165
  1176
    }
deba@165
  1177
deba@165
  1178
    /// \brief Node map writing rule
deba@165
  1179
    ///
deba@165
  1180
    /// Add a node map writing rule with specialized converter to the
deba@165
  1181
    /// writer.
deba@165
  1182
    template <typename Map, typename Converter>
alpar@209
  1183
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
  1184
                           const Converter& converter = Converter()) {
deba@165
  1185
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1186
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1187
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1188
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1189
      return *this;
deba@165
  1190
    }
deba@165
  1191
deba@165
  1192
    /// \brief Edge map writing rule
deba@165
  1193
    ///
deba@165
  1194
    /// Add an edge map writing rule to the writer.
deba@165
  1195
    template <typename Map>
deba@165
  1196
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1197
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1198
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1199
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1200
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1201
      return *this;
deba@165
  1202
    }
deba@165
  1203
deba@165
  1204
    /// \brief Edge map writing rule
deba@165
  1205
    ///
deba@165
  1206
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1207
    /// writer.
deba@165
  1208
    template <typename Map, typename Converter>
alpar@209
  1209
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
alpar@209
  1210
                          const Converter& converter = Converter()) {
deba@165
  1211
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1212
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1213
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1214
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1215
      return *this;
deba@165
  1216
    }
deba@165
  1217
deba@165
  1218
    /// \brief Arc map writing rule
deba@165
  1219
    ///
deba@165
  1220
    /// Add an arc map writing rule to the writer.
deba@165
  1221
    template <typename Map>
deba@165
  1222
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1223
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1224
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1225
        new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
deba@165
  1226
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1227
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1228
        new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1229
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1230
      return *this;
deba@165
  1231
    }
deba@165
  1232
deba@165
  1233
    /// \brief Arc map writing rule
deba@165
  1234
    ///
deba@165
  1235
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1236
    /// writer.
deba@165
  1237
    template <typename Map, typename Converter>
alpar@209
  1238
    GraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
  1239
                          const Converter& converter = Converter()) {
deba@165
  1240
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1241
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@598
  1242
        new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1243
        (_graph, map, converter);
deba@165
  1244
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1245
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@598
  1246
        new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1247
        (_graph, map, converter);
deba@165
  1248
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1249
      return *this;
deba@165
  1250
    }
deba@165
  1251
deba@165
  1252
    /// \brief Attribute writing rule
deba@165
  1253
    ///
deba@165
  1254
    /// Add an attribute writing rule to the writer.
deba@165
  1255
    template <typename Value>
deba@165
  1256
    GraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
  1257
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1258
        new _writer_bits::ValueStorage<Value>(value);
deba@165
  1259
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1260
      return *this;
deba@165
  1261
    }
deba@165
  1262
deba@165
  1263
    /// \brief Attribute writing rule
deba@165
  1264
    ///
deba@165
  1265
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1266
    /// writer.
deba@165
  1267
    template <typename Value, typename Converter>
alpar@209
  1268
    GraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
  1269
                             const Converter& converter = Converter()) {
alpar@209
  1270
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1271
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1272
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1273
      return *this;
deba@165
  1274
    }
deba@165
  1275
deba@165
  1276
    /// \brief Node writing rule
deba@165
  1277
    ///
deba@165
  1278
    /// Add a node writing rule to the writer.
deba@165
  1279
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1280
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1281
      Converter converter(_node_index);
alpar@209
  1282
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1283
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1284
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1285
      return *this;
deba@165
  1286
    }
deba@165
  1287
deba@165
  1288
    /// \brief Edge writing rule
deba@165
  1289
    ///
deba@165
  1290
    /// Add an edge writing rule to writer.
deba@165
  1291
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1292
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1293
      Converter converter(_edge_index);
alpar@209
  1294
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1295
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1296
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1297
      return *this;
deba@165
  1298
    }
deba@165
  1299
deba@165
  1300
    /// \brief Arc writing rule
deba@165
  1301
    ///
deba@165
  1302
    /// Add an arc writing rule to writer.
deba@165
  1303
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@598
  1304
      typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1305
      Converter converter(_graph, _edge_index);
alpar@209
  1306
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1307
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1308
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1309
      return *this;
deba@165
  1310
    }
deba@165
  1311
kpeter@584
  1312
    /// \name Section Captions
deba@165
  1313
    /// @{
deba@165
  1314
kpeter@192
  1315
    /// \brief Add an additional caption to the \c \@nodes section
deba@165
  1316
    ///
kpeter@192
  1317
    /// Add an additional caption to the \c \@nodes section.
deba@165
  1318
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1319
      _nodes_caption = caption;
deba@165
  1320
      return *this;
deba@165
  1321
    }
deba@165
  1322
deba@1024
  1323
    /// \brief Add an additional caption to the \c \@edges section
deba@165
  1324
    ///
deba@1024
  1325
    /// Add an additional caption to the \c \@edges section.
deba@165
  1326
    GraphWriter& edges(const std::string& caption) {
deba@165
  1327
      _edges_caption = caption;
deba@165
  1328
      return *this;
deba@165
  1329
    }
deba@165
  1330
kpeter@192
  1331
    /// \brief Add an additional caption to the \c \@attributes section
deba@165
  1332
    ///
kpeter@192
  1333
    /// Add an additional caption to the \c \@attributes section.
deba@165
  1334
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1335
      _attributes_caption = caption;
deba@165
  1336
      return *this;
deba@165
  1337
    }
deba@165
  1338
kpeter@584
  1339
    /// \name Skipping Section
deba@165
  1340
    /// @{
deba@165
  1341
deba@165
  1342
    /// \brief Skip writing the node set
deba@165
  1343
    ///
kpeter@192
  1344
    /// The \c \@nodes section will not be written to the stream.
deba@165
  1345
    GraphWriter& skipNodes() {
deba@165
  1346
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1347
      _skip_nodes = true;
deba@165
  1348
      return *this;
deba@165
  1349
    }
deba@165
  1350
deba@165
  1351
    /// \brief Skip writing edge set
deba@165
  1352
    ///
kpeter@192
  1353
    /// The \c \@edges section will not be written to the stream.
deba@165
  1354
    GraphWriter& skipEdges() {
deba@165
  1355
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1356
      _skip_edges = true;
deba@165
  1357
      return *this;
deba@165
  1358
    }
deba@165
  1359
deba@165
  1360
    /// @}
deba@165
  1361
deba@165
  1362
  private:
deba@165
  1363
deba@165
  1364
    void writeNodes() {
deba@165
  1365
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1366
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1367
           it != _node_maps.end(); ++it) {
deba@165
  1368
        if (it->first == "label") {
alpar@209
  1369
          label = it->second;
alpar@209
  1370
          break;
alpar@209
  1371
        }
deba@165
  1372
      }
deba@165
  1373
deba@165
  1374
      *_os << "@nodes";
deba@165
  1375
      if (!_nodes_caption.empty()) {
alpar@209
  1376
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1377
      }
deba@165
  1378
      *_os << std::endl;
deba@165
  1379
deba@165
  1380
      if (label == 0) {
alpar@209
  1381
        *_os << "label" << '\t';
deba@165
  1382
      }
deba@165
  1383
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1384
           it != _node_maps.end(); ++it) {
alpar@209
  1385
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1386
      }
deba@165
  1387
      *_os << std::endl;
deba@165
  1388
deba@165
  1389
      std::vector<Node> nodes;
deba@165
  1390
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1391
        nodes.push_back(n);
deba@165
  1392
      }
alpar@209
  1393
deba@165
  1394
      if (label == 0) {
deba@598
  1395
        IdMap<GR, Node> id_map(_graph);
deba@598
  1396
        _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
alpar@209
  1397
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1398
      } else {
alpar@209
  1399
        label->sort(nodes);
deba@165
  1400
      }
deba@165
  1401
deba@165
  1402
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
  1403
        Node n = nodes[i];
alpar@209
  1404
        if (label == 0) {
alpar@209
  1405
          std::ostringstream os;
alpar@209
  1406
          os << _graph.id(n);
alpar@209
  1407
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1408
          *_os << '\t';
alpar@209
  1409
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1410
        }
alpar@209
  1411
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1412
             it != _node_maps.end(); ++it) {
alpar@209
  1413
          std::string value = it->second->get(n);
alpar@209
  1414
          _writer_bits::writeToken(*_os, value);
alpar@209
  1415
          if (it->first == "label") {
alpar@209
  1416
            _node_index.insert(std::make_pair(n, value));
alpar@209
  1417
          }
alpar@209
  1418
          *_os << '\t';
alpar@209
  1419
        }
alpar@209
  1420
        *_os << std::endl;
deba@165
  1421
      }
deba@165
  1422
    }
deba@165
  1423
deba@185
  1424
    void createNodeIndex() {
deba@185
  1425
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1426
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1427
           it != _node_maps.end(); ++it) {
deba@185
  1428
        if (it->first == "label") {
alpar@209
  1429
          label = it->second;
alpar@209
  1430
          break;
alpar@209
  1431
        }
deba@185
  1432
      }
deba@185
  1433
deba@185
  1434
      if (label == 0) {
alpar@209
  1435
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1436
          std::ostringstream os;
alpar@209
  1437
          os << _graph.id(n);
alpar@209
  1438
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1439
        }
deba@185
  1440
      } else {
alpar@209
  1441
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1442
          std::string value = label->get(n);
alpar@209
  1443
          _node_index.insert(std::make_pair(n, value));
alpar@209
  1444
        }
deba@185
  1445
      }
deba@185
  1446
    }
deba@185
  1447
deba@165
  1448
    void writeEdges() {
deba@165
  1449
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1450
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1451
           it != _edge_maps.end(); ++it) {
deba@165
  1452
        if (it->first == "label") {
alpar@209
  1453
          label = it->second;
alpar@209
  1454
          break;
alpar@209
  1455
        }
deba@165
  1456
      }
deba@165
  1457
deba@165
  1458
      *_os << "@edges";
deba@165
  1459
      if (!_edges_caption.empty()) {
alpar@209
  1460
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1461
      }
deba@165
  1462
      *_os << std::endl;
deba@165
  1463
deba@165
  1464
      *_os << '\t' << '\t';
deba@165
  1465
      if (label == 0) {
alpar@209
  1466
        *_os << "label" << '\t';
deba@165
  1467
      }
deba@165
  1468
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1469
           it != _edge_maps.end(); ++it) {
alpar@209
  1470
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1471
      }
deba@165
  1472
      *_os << std::endl;
deba@165
  1473
deba@165
  1474
      std::vector<Edge> edges;
deba@165
  1475
      for (EdgeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1476
        edges.push_back(n);
deba@165
  1477
      }
alpar@209
  1478
deba@165
  1479
      if (label == 0) {
deba@598
  1480
        IdMap<GR, Edge> id_map(_graph);
deba@598
  1481
        _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
alpar@209
  1482
        std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1483
      } else {
alpar@209
  1484
        label->sort(edges);
deba@165
  1485
      }
deba@165
  1486
deba@165
  1487
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
alpar@209
  1488
        Edge e = edges[i];
alpar@209
  1489
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1490
                                 find(_graph.u(e))->second);
alpar@209
  1491
        *_os << '\t';
alpar@209
  1492
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1493
                                 find(_graph.v(e))->second);
alpar@209
  1494
        *_os << '\t';
alpar@209
  1495
        if (label == 0) {
alpar@209
  1496
          std::ostringstream os;
alpar@209
  1497
          os << _graph.id(e);
alpar@209
  1498
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1499
          *_os << '\t';
alpar@209
  1500
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1501
        }
alpar@209
  1502
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1503
             it != _edge_maps.end(); ++it) {
alpar@209
  1504
          std::string value = it->second->get(e);
alpar@209
  1505
          _writer_bits::writeToken(*_os, value);
alpar@209
  1506
          if (it->first == "label") {
alpar@209
  1507
            _edge_index.insert(std::make_pair(e, value));
alpar@209
  1508
          }
alpar@209
  1509
          *_os << '\t';
alpar@209
  1510
        }
alpar@209
  1511
        *_os << std::endl;
deba@165
  1512
      }
deba@165
  1513
    }
deba@165
  1514
deba@185
  1515
    void createEdgeIndex() {
deba@185
  1516
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1517
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1518
           it != _edge_maps.end(); ++it) {
deba@185
  1519
        if (it->first == "label") {
alpar@209
  1520
          label = it->second;
alpar@209
  1521
          break;
alpar@209
  1522
        }
deba@185
  1523
      }
deba@185
  1524
deba@185
  1525
      if (label == 0) {
alpar@209
  1526
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1527
          std::ostringstream os;
alpar@209
  1528
          os << _graph.id(e);
alpar@209
  1529
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1530
        }
deba@185
  1531
      } else {
alpar@209
  1532
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1533
          std::string value = label->get(e);
alpar@209
  1534
          _edge_index.insert(std::make_pair(e, value));
alpar@209
  1535
        }
deba@185
  1536
      }
deba@185
  1537
    }
deba@185
  1538
deba@165
  1539
    void writeAttributes() {
deba@165
  1540
      if (_attributes.empty()) return;
deba@165
  1541
      *_os << "@attributes";
deba@165
  1542
      if (!_attributes_caption.empty()) {
alpar@209
  1543
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1544
      }
deba@165
  1545
      *_os << std::endl;
deba@165
  1546
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1547
           it != _attributes.end(); ++it) {
alpar@209
  1548
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
  1549
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
  1550
        *_os << std::endl;
deba@165
  1551
      }
deba@165
  1552
    }
alpar@209
  1553
deba@165
  1554
  public:
alpar@209
  1555
kpeter@584
  1556
    /// \name Execution of the Writer
deba@165
  1557
    /// @{
deba@165
  1558
deba@165
  1559
    /// \brief Start the batch processing
deba@165
  1560
    ///
kpeter@192
  1561
    /// This function starts the batch processing.
deba@165
  1562
    void run() {
deba@165
  1563
      if (!_skip_nodes) {
alpar@209
  1564
        writeNodes();
deba@185
  1565
      } else {
alpar@209
  1566
        createNodeIndex();
deba@165
  1567
      }
alpar@209
  1568
      if (!_skip_edges) {
alpar@209
  1569
        writeEdges();
deba@185
  1570
      } else {
alpar@209
  1571
        createEdgeIndex();
deba@165
  1572
      }
deba@165
  1573
      writeAttributes();
deba@165
  1574
    }
deba@165
  1575
kpeter@192
  1576
    /// \brief Give back the stream of the writer
deba@165
  1577
    ///
kpeter@192
  1578
    /// Give back the stream of the writer
deba@165
  1579
    std::ostream& ostream() {
deba@165
  1580
      return *_os;
deba@165
  1581
    }
deba@165
  1582
deba@165
  1583
    /// @}
deba@165
  1584
  };
deba@165
  1585
deba@598
  1586
  /// \ingroup lemon_io
deba@598
  1587
  ///
alpar@1076
  1588
  /// \brief Return a \ref lemon::GraphWriter "GraphWriter" class
kpeter@487
  1589
  ///
alpar@1076
  1590
  /// This function just returns a \ref lemon::GraphWriter "GraphWriter" class.
deba@598
  1591
  ///
deba@598
  1592
  /// With this function a graph can be write to a file or output
deba@598
  1593
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@598
  1594
  /// attributes. For example, with the following code a weighted
deba@598
  1595
  /// matching problem can be written to the standard output, i.e. a
deba@598
  1596
  /// graph with a \e weight map on the edges:
deba@598
  1597
  ///
deba@598
  1598
  ///\code
deba@598
  1599
  ///ListGraph graph;
deba@598
  1600
  ///ListGraph::EdgeMap<int> weight(graph);
deba@598
  1601
  ///  // Setting the weight map
deba@598
  1602
  ///graphWriter(graph, std::cout).
deba@598
  1603
  ///  edgeMap("weight", weight).
deba@598
  1604
  ///  run();
deba@598
  1605
  ///\endcode
deba@598
  1606
  ///
alpar@1076
  1607
  /// For a complete documentation, please see the
alpar@1076
  1608
  /// \ref lemon::GraphWriter "GraphWriter"
deba@598
  1609
  /// class documentation.
alpar@1076
  1610
  /// \warning Don't forget to put the \ref lemon::GraphWriter::run() "run()"
deba@598
  1611
  /// to the end of the parameter list.
kpeter@487
  1612
  /// \relates GraphWriter
deba@598
  1613
  /// \sa graphWriter(const TGR& graph, const std::string& fn)
deba@598
  1614
  /// \sa graphWriter(const TGR& graph, const char* fn)
deba@598
  1615
  template <typename TGR>
deba@598
  1616
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
deba@598
  1617
    GraphWriter<TGR> tmp(graph, os);
kpeter@487
  1618
    return tmp;
kpeter@487
  1619
  }
kpeter@487
  1620
kpeter@487
  1621
  /// \brief Return a \ref GraphWriter class
kpeter@487
  1622
  ///
kpeter@487
  1623
  /// This function just returns a \ref GraphWriter class.
kpeter@487
  1624
  /// \relates GraphWriter
deba@598
  1625
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1626
  template <typename TGR>
deba@598
  1627
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
deba@598
  1628
    GraphWriter<TGR> tmp(graph, fn);
kpeter@487
  1629
    return tmp;
kpeter@487
  1630
  }
kpeter@487
  1631
kpeter@487
  1632
  /// \brief Return a \ref GraphWriter class
kpeter@487
  1633
  ///
kpeter@487
  1634
  /// This function just returns a \ref GraphWriter class.
kpeter@487
  1635
  /// \relates GraphWriter
deba@598
  1636
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@598
  1637
  template <typename TGR>
deba@598
  1638
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
deba@598
  1639
    GraphWriter<TGR> tmp(graph, fn);
kpeter@487
  1640
    return tmp;
kpeter@487
  1641
  }
kpeter@487
  1642
deba@1024
  1643
  template <typename BGR>
deba@1024
  1644
  class BpGraphWriter;
deba@1024
  1645
deba@1024
  1646
  template <typename TBGR>
deba@1024
  1647
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1648
                                    std::ostream& os = std::cout);
deba@1024
  1649
  template <typename TBGR>
deba@1024
  1650
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
deba@1024
  1651
  template <typename TBGR>
deba@1024
  1652
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
deba@1024
  1653
deba@1024
  1654
  /// \ingroup lemon_io
deba@1024
  1655
  ///
deba@1024
  1656
  /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
deba@1024
  1657
  ///
deba@1024
  1658
  /// This utility writes an \ref lgf-format "LGF" file.
deba@1024
  1659
  ///
deba@1024
  1660
  /// It can be used almost the same way as \c GraphWriter, but it
deba@1024
  1661
  /// reads the red and blue nodes from separate sections, and these
deba@1024
  1662
  /// sections can contain different set of maps.
deba@1024
  1663
  ///
deba@1026
  1664
  /// The red and blue node maps are written to the corresponding
deba@1024
  1665
  /// sections. The node maps are written to both of these sections
deba@1024
  1666
  /// with the same map name.
deba@1024
  1667
  template <typename BGR>
deba@1024
  1668
  class BpGraphWriter {
deba@1024
  1669
  public:
deba@1024
  1670
deba@1024
  1671
    typedef BGR BpGraph;
deba@1024
  1672
    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
deba@1024
  1673
deba@1024
  1674
  private:
deba@1024
  1675
deba@1024
  1676
deba@1024
  1677
    std::ostream* _os;
deba@1024
  1678
    bool local_os;
deba@1024
  1679
deba@1024
  1680
    const BGR& _graph;
deba@1024
  1681
deba@1024
  1682
    std::string _nodes_caption;
deba@1024
  1683
    std::string _edges_caption;
deba@1024
  1684
    std::string _attributes_caption;
deba@1024
  1685
deba@1030
  1686
    typedef std::map<Node, std::string> RedNodeIndex;
deba@1030
  1687
    RedNodeIndex _red_node_index;
deba@1030
  1688
    typedef std::map<Node, std::string> BlueNodeIndex;
deba@1030
  1689
    BlueNodeIndex _blue_node_index;
deba@1024
  1690
    typedef std::map<Edge, std::string> EdgeIndex;
deba@1024
  1691
    EdgeIndex _edge_index;
deba@1024
  1692
deba@1024
  1693
    typedef std::vector<std::pair<std::string,
deba@1030
  1694
      _writer_bits::MapStorageBase<RedNode>* > > RedNodeMaps;
deba@1030
  1695
    RedNodeMaps _red_node_maps;
deba@1030
  1696
    typedef std::vector<std::pair<std::string,
deba@1030
  1697
      _writer_bits::MapStorageBase<BlueNode>* > > BlueNodeMaps;
deba@1030
  1698
    BlueNodeMaps _blue_node_maps;
deba@1024
  1699
deba@1024
  1700
    typedef std::vector<std::pair<std::string,
deba@1024
  1701
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@1024
  1702
    EdgeMaps _edge_maps;
deba@1024
  1703
deba@1024
  1704
    typedef std::vector<std::pair<std::string,
deba@1024
  1705
      _writer_bits::ValueStorageBase*> > Attributes;
deba@1024
  1706
    Attributes _attributes;
deba@1024
  1707
deba@1024
  1708
    bool _skip_nodes;
deba@1024
  1709
    bool _skip_edges;
deba@1024
  1710
deba@1024
  1711
  public:
deba@1024
  1712
deba@1024
  1713
    /// \brief Constructor
deba@1024
  1714
    ///
deba@1024
  1715
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1716
    /// output stream.
deba@1024
  1717
    BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
deba@1024
  1718
      : _os(&os), local_os(false), _graph(graph),
deba@1024
  1719
        _skip_nodes(false), _skip_edges(false) {}
deba@1024
  1720
deba@1024
  1721
    /// \brief Constructor
deba@1024
  1722
    ///
deba@1024
  1723
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1724
    /// output file.
deba@1024
  1725
    BpGraphWriter(const BGR& graph, const std::string& fn)
deba@1024
  1726
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@1024
  1727
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1728
      if (!(*_os)) {
deba@1024
  1729
        delete _os;
deba@1024
  1730
        throw IoError("Cannot write file", fn);
deba@1024
  1731
      }
deba@1024
  1732
    }
deba@1024
  1733
deba@1024
  1734
    /// \brief Constructor
deba@1024
  1735
    ///
deba@1024
  1736
    /// Construct a bipartite graph writer, which writes to the given
deba@1024
  1737
    /// output file.
deba@1024
  1738
    BpGraphWriter(const BGR& graph, const char* fn)
deba@1024
  1739
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@1024
  1740
        _skip_nodes(false), _skip_edges(false) {
deba@1024
  1741
      if (!(*_os)) {
deba@1024
  1742
        delete _os;
deba@1024
  1743
        throw IoError("Cannot write file", fn);
deba@1024
  1744
      }
deba@1024
  1745
    }
deba@1024
  1746
deba@1024
  1747
    /// \brief Destructor
deba@1024
  1748
    ~BpGraphWriter() {
deba@1030
  1749
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  1750
           it != _red_node_maps.end(); ++it) {
deba@1024
  1751
        delete it->second;
deba@1024
  1752
      }
deba@1024
  1753
deba@1030
  1754
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  1755
           it != _blue_node_maps.end(); ++it) {
deba@1024
  1756
        delete it->second;
deba@1024
  1757
      }
deba@1024
  1758
deba@1024
  1759
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  1760
           it != _edge_maps.end(); ++it) {
deba@1024
  1761
        delete it->second;
deba@1024
  1762
      }
deba@1024
  1763
deba@1024
  1764
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  1765
           it != _attributes.end(); ++it) {
deba@1024
  1766
        delete it->second;
deba@1024
  1767
      }
deba@1024
  1768
deba@1024
  1769
      if (local_os) {
deba@1024
  1770
        delete _os;
deba@1024
  1771
      }
deba@1024
  1772
    }
deba@1024
  1773
deba@1024
  1774
  private:
deba@1024
  1775
deba@1024
  1776
    template <typename TBGR>
deba@1024
  1777
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1778
                                             std::ostream& os);
deba@1024
  1779
    template <typename TBGR>
deba@1024
  1780
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
deba@1024
  1781
                                             const std::string& fn);
deba@1024
  1782
    template <typename TBGR>
deba@1024
  1783
    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
deba@1024
  1784
deba@1024
  1785
    BpGraphWriter(BpGraphWriter& other)
deba@1024
  1786
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
deba@1024
  1787
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@1024
  1788
deba@1024
  1789
      other._os = 0;
deba@1024
  1790
      other.local_os = false;
deba@1024
  1791
deba@1030
  1792
      _red_node_index.swap(other._red_node_index);
deba@1030
  1793
      _blue_node_index.swap(other._blue_node_index);
deba@1024
  1794
      _edge_index.swap(other._edge_index);
deba@1024
  1795
deba@1030
  1796
      _red_node_maps.swap(other._red_node_maps);
deba@1030
  1797
      _blue_node_maps.swap(other._blue_node_maps);
deba@1024
  1798
      _edge_maps.swap(other._edge_maps);
deba@1024
  1799
      _attributes.swap(other._attributes);
deba@1024
  1800
deba@1024
  1801
      _nodes_caption = other._nodes_caption;
deba@1024
  1802
      _edges_caption = other._edges_caption;
deba@1024
  1803
      _attributes_caption = other._attributes_caption;
deba@1024
  1804
    }
deba@1024
  1805
deba@1024
  1806
    BpGraphWriter& operator=(const BpGraphWriter&);
deba@1024
  1807
deba@1024
  1808
  public:
deba@1024
  1809
deba@1024
  1810
    /// \name Writing Rules
deba@1024
  1811
    /// @{
deba@1024
  1812
deba@1024
  1813
    /// \brief Node map writing rule
deba@1024
  1814
    ///
deba@1024
  1815
    /// Add a node map writing rule to the writer.
deba@1024
  1816
    template <typename Map>
deba@1024
  1817
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@1024
  1818
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1030
  1819
      _writer_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  1820
        new _writer_bits::MapStorage<RedNode, Map>(map);
deba@1030
  1821
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  1822
      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  1823
        new _writer_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  1824
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1825
      return *this;
deba@1024
  1826
    }
deba@1024
  1827
deba@1024
  1828
    /// \brief Node map writing rule
deba@1024
  1829
    ///
deba@1024
  1830
    /// Add a node map writing rule with specialized converter to the
deba@1024
  1831
    /// writer.
deba@1024
  1832
    template <typename Map, typename Converter>
deba@1024
  1833
    BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
deba@1024
  1834
                           const Converter& converter = Converter()) {
deba@1024
  1835
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
deba@1030
  1836
      _writer_bits::MapStorageBase<RedNode>* red_storage =
deba@1030
  1837
        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  1838
      _red_node_maps.push_back(std::make_pair(caption, red_storage));
deba@1030
  1839
      _writer_bits::MapStorageBase<BlueNode>* blue_storage =
deba@1030
  1840
        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  1841
      _blue_node_maps.push_back(std::make_pair(caption, blue_storage));
deba@1024
  1842
      return *this;
deba@1024
  1843
    }
deba@1024
  1844
deba@1026
  1845
    /// \brief Red node map writing rule
deba@1024
  1846
    ///
deba@1026
  1847
    /// Add a red node map writing rule to the writer.
deba@1024
  1848
    template <typename Map>
deba@1026
  1849
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map) {
deba@1030
  1850
      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
deba@1030
  1851
      _writer_bits::MapStorageBase<RedNode>* storage =
deba@1030
  1852
        new _writer_bits::MapStorage<RedNode, Map>(map);
deba@1030
  1853
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1854
      return *this;
deba@1024
  1855
    }
deba@1024
  1856
deba@1026
  1857
    /// \brief Red node map writing rule
deba@1024
  1858
    ///
deba@1026
  1859
    /// Add a red node map writing rule with specialized converter to the
deba@1024
  1860
    /// writer.
deba@1024
  1861
    template <typename Map, typename Converter>
deba@1026
  1862
    BpGraphWriter& redNodeMap(const std::string& caption, const Map& map,
deba@1026
  1863
                              const Converter& converter = Converter()) {
deba@1030
  1864
      checkConcept<concepts::ReadMap<RedNode, typename Map::Value>, Map>();
deba@1030
  1865
      _writer_bits::MapStorageBase<RedNode>* storage =
deba@1030
  1866
        new _writer_bits::MapStorage<RedNode, Map, Converter>(map, converter);
deba@1030
  1867
      _red_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1868
      return *this;
deba@1024
  1869
    }
deba@1024
  1870
deba@1026
  1871
    /// \brief Blue node map writing rule
deba@1024
  1872
    ///
deba@1026
  1873
    /// Add a blue node map writing rule to the writer.
deba@1024
  1874
    template <typename Map>
deba@1026
  1875
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map) {
deba@1030
  1876
      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  1877
      _writer_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  1878
        new _writer_bits::MapStorage<BlueNode, Map>(map);
deba@1030
  1879
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1880
      return *this;
deba@1024
  1881
    }
deba@1024
  1882
deba@1026
  1883
    /// \brief Blue node map writing rule
deba@1024
  1884
    ///
deba@1026
  1885
    /// Add a blue node map writing rule with specialized converter to the
deba@1024
  1886
    /// writer.
deba@1024
  1887
    template <typename Map, typename Converter>
deba@1026
  1888
    BpGraphWriter& blueNodeMap(const std::string& caption, const Map& map,
deba@1026
  1889
                               const Converter& converter = Converter()) {
deba@1030
  1890
      checkConcept<concepts::ReadMap<BlueNode, typename Map::Value>, Map>();
deba@1030
  1891
      _writer_bits::MapStorageBase<BlueNode>* storage =
deba@1030
  1892
        new _writer_bits::MapStorage<BlueNode, Map, Converter>(map, converter);
deba@1030
  1893
      _blue_node_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1894
      return *this;
deba@1024
  1895
    }
deba@1024
  1896
deba@1024
  1897
    /// \brief Edge map writing rule
deba@1024
  1898
    ///
deba@1024
  1899
    /// Add an edge map writing rule to the writer.
deba@1024
  1900
    template <typename Map>
deba@1024
  1901
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@1024
  1902
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1903
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1904
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@1024
  1905
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1906
      return *this;
deba@1024
  1907
    }
deba@1024
  1908
deba@1024
  1909
    /// \brief Edge map writing rule
deba@1024
  1910
    ///
deba@1024
  1911
    /// Add an edge map writing rule with specialized converter to the
deba@1024
  1912
    /// writer.
deba@1024
  1913
    template <typename Map, typename Converter>
deba@1024
  1914
    BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
deba@1024
  1915
                          const Converter& converter = Converter()) {
deba@1024
  1916
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
deba@1024
  1917
      _writer_bits::MapStorageBase<Edge>* storage =
deba@1024
  1918
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@1024
  1919
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@1024
  1920
      return *this;
deba@1024
  1921
    }
deba@1024
  1922
deba@1024
  1923
    /// \brief Arc map writing rule
deba@1024
  1924
    ///
deba@1024
  1925
    /// Add an arc map writing rule to the writer.
deba@1024
  1926
    template <typename Map>
deba@1024
  1927
    BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@1024
  1928
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1929
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1930
        new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
deba@1024
  1931
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1932
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1933
        new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
deba@1024
  1934
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1935
      return *this;
deba@1024
  1936
    }
deba@1024
  1937
deba@1024
  1938
    /// \brief Arc map writing rule
deba@1024
  1939
    ///
deba@1024
  1940
    /// Add an arc map writing rule with specialized converter to the
deba@1024
  1941
    /// writer.
deba@1024
  1942
    template <typename Map, typename Converter>
deba@1024
  1943
    BpGraphWriter& arcMap(const std::string& caption, const Map& map,
deba@1024
  1944
                          const Converter& converter = Converter()) {
deba@1024
  1945
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
deba@1024
  1946
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@1024
  1947
        new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
deba@1024
  1948
        (_graph, map, converter);
deba@1024
  1949
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
deba@1024
  1950
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@1024
  1951
        new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
deba@1024
  1952
        (_graph, map, converter);
deba@1024
  1953
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@1024
  1954
      return *this;
deba@1024
  1955
    }
deba@1024
  1956
deba@1024
  1957
    /// \brief Attribute writing rule
deba@1024
  1958
    ///
deba@1024
  1959
    /// Add an attribute writing rule to the writer.
deba@1024
  1960
    template <typename Value>
deba@1024
  1961
    BpGraphWriter& attribute(const std::string& caption, const Value& value) {
deba@1024
  1962
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1963
        new _writer_bits::ValueStorage<Value>(value);
deba@1024
  1964
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1965
      return *this;
deba@1024
  1966
    }
deba@1024
  1967
deba@1024
  1968
    /// \brief Attribute writing rule
deba@1024
  1969
    ///
deba@1024
  1970
    /// Add an attribute writing rule with specialized converter to the
deba@1024
  1971
    /// writer.
deba@1024
  1972
    template <typename Value, typename Converter>
deba@1024
  1973
    BpGraphWriter& attribute(const std::string& caption, const Value& value,
deba@1024
  1974
                             const Converter& converter = Converter()) {
deba@1024
  1975
      _writer_bits::ValueStorageBase* storage =
deba@1024
  1976
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@1024
  1977
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  1978
      return *this;
deba@1024
  1979
    }
deba@1024
  1980
deba@1024
  1981
    /// \brief Node writing rule
deba@1024
  1982
    ///
deba@1024
  1983
    /// Add a node writing rule to the writer.
deba@1024
  1984
    BpGraphWriter& node(const std::string& caption, const Node& node) {
deba@1030
  1985
      typedef _writer_bits::DoubleMapLookUpConverter<
deba@1030
  1986
        Node, RedNodeIndex, BlueNodeIndex> Converter;
deba@1030
  1987
      Converter converter(_red_node_index, _blue_node_index);
deba@1030
  1988
      _writer_bits::ValueStorageBase* storage =
deba@1030
  1989
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1030
  1990
      _attributes.push_back(std::make_pair(caption, storage));
deba@1030
  1991
      return *this;
deba@1030
  1992
    }
deba@1030
  1993
deba@1030
  1994
    /// \brief Red node writing rule
deba@1030
  1995
    ///
deba@1030
  1996
    /// Add a red node writing rule to the writer.
deba@1030
  1997
    BpGraphWriter& redNode(const std::string& caption, const RedNode& node) {
deba@1024
  1998
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@1030
  1999
      Converter converter(_red_node_index);
deba@1030
  2000
      _writer_bits::ValueStorageBase* storage =
deba@1030
  2001
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1030
  2002
      _attributes.push_back(std::make_pair(caption, storage));
deba@1030
  2003
      return *this;
deba@1030
  2004
    }
deba@1030
  2005
deba@1030
  2006
    /// \brief Blue node writing rule
deba@1030
  2007
    ///
deba@1030
  2008
    /// Add a blue node writing rule to the writer.
deba@1030
  2009
    BpGraphWriter& blueNode(const std::string& caption, const BlueNode& node) {
deba@1030
  2010
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@1030
  2011
      Converter converter(_blue_node_index);
deba@1024
  2012
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2013
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@1024
  2014
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2015
      return *this;
deba@1024
  2016
    }
deba@1024
  2017
deba@1024
  2018
    /// \brief Edge writing rule
deba@1024
  2019
    ///
deba@1024
  2020
    /// Add an edge writing rule to writer.
deba@1024
  2021
    BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@1024
  2022
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@1024
  2023
      Converter converter(_edge_index);
deba@1024
  2024
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2025
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@1024
  2026
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2027
      return *this;
deba@1024
  2028
    }
deba@1024
  2029
deba@1024
  2030
    /// \brief Arc writing rule
deba@1024
  2031
    ///
deba@1024
  2032
    /// Add an arc writing rule to writer.
deba@1024
  2033
    BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@1024
  2034
      typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
deba@1024
  2035
      Converter converter(_graph, _edge_index);
deba@1024
  2036
      _writer_bits::ValueStorageBase* storage =
deba@1024
  2037
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@1024
  2038
      _attributes.push_back(std::make_pair(caption, storage));
deba@1024
  2039
      return *this;
deba@1024
  2040
    }
deba@1024
  2041
deba@1024
  2042
    /// \name Section Captions
deba@1024
  2043
    /// @{
deba@1024
  2044
deba@1024
  2045
    /// \brief Add an additional caption to the \c \@red_nodes and
deba@1024
  2046
    /// \c \@blue_nodes section
deba@1024
  2047
    ///
deba@1024
  2048
    /// Add an additional caption to the \c \@red_nodes and \c
deba@1024
  2049
    /// \@blue_nodes section.
deba@1024
  2050
    BpGraphWriter& nodes(const std::string& caption) {
deba@1024
  2051
      _nodes_caption = caption;
deba@1024
  2052
      return *this;
deba@1024
  2053
    }
deba@1024
  2054
deba@1024
  2055
    /// \brief Add an additional caption to the \c \@edges section
deba@1024
  2056
    ///
deba@1024
  2057
    /// Add an additional caption to the \c \@edges section.
deba@1024
  2058
    BpGraphWriter& edges(const std::string& caption) {
deba@1024
  2059
      _edges_caption = caption;
deba@1024
  2060
      return *this;
deba@1024
  2061
    }
deba@1024
  2062
deba@1024
  2063
    /// \brief Add an additional caption to the \c \@attributes section
deba@1024
  2064
    ///
deba@1024
  2065
    /// Add an additional caption to the \c \@attributes section.
deba@1024
  2066
    BpGraphWriter& attributes(const std::string& caption) {
deba@1024
  2067
      _attributes_caption = caption;
deba@1024
  2068
      return *this;
deba@1024
  2069
    }
deba@1024
  2070
deba@1024
  2071
    /// \name Skipping Section
deba@1024
  2072
    /// @{
deba@1024
  2073
deba@1024
  2074
    /// \brief Skip writing the node set
deba@1024
  2075
    ///
deba@1024
  2076
    /// The \c \@red_nodes and \c \@blue_nodes section will not be
deba@1024
  2077
    /// written to the stream.
deba@1024
  2078
    BpGraphWriter& skipNodes() {
deba@1024
  2079
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@1024
  2080
      _skip_nodes = true;
deba@1024
  2081
      return *this;
deba@1024
  2082
    }
deba@1024
  2083
deba@1024
  2084
    /// \brief Skip writing edge set
deba@1024
  2085
    ///
deba@1024
  2086
    /// The \c \@edges section will not be written to the stream.
deba@1024
  2087
    BpGraphWriter& skipEdges() {
deba@1024
  2088
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@1024
  2089
      _skip_edges = true;
deba@1024
  2090
      return *this;
deba@1024
  2091
    }
deba@1024
  2092
deba@1024
  2093
    /// @}
deba@1024
  2094
deba@1024
  2095
  private:
deba@1024
  2096
deba@1024
  2097
    void writeRedNodes() {
deba@1030
  2098
      _writer_bits::MapStorageBase<RedNode>* label = 0;
deba@1030
  2099
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2100
           it != _red_node_maps.end(); ++it) {
deba@1024
  2101
        if (it->first == "label") {
deba@1024
  2102
          label = it->second;
deba@1024
  2103
          break;
deba@1024
  2104
        }
deba@1024
  2105
      }
deba@1024
  2106
deba@1024
  2107
      *_os << "@red_nodes";
deba@1024
  2108
      if (!_nodes_caption.empty()) {
deba@1024
  2109
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2110
      }
deba@1024
  2111
      *_os << std::endl;
deba@1024
  2112
deba@1024
  2113
      if (label == 0) {
deba@1024
  2114
        *_os << "label" << '\t';
deba@1024
  2115
      }
deba@1030
  2116
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2117
           it != _red_node_maps.end(); ++it) {
deba@1024
  2118
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2119
      }
deba@1024
  2120
      *_os << std::endl;
deba@1024
  2121
deba@1030
  2122
      std::vector<RedNode> nodes;
deba@1026
  2123
      for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2124
        nodes.push_back(n);
deba@1024
  2125
      }
deba@1024
  2126
deba@1024
  2127
      if (label == 0) {
deba@1024
  2128
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2129
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2130
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2131
      } else {
deba@1024
  2132
        label->sort(nodes);
deba@1024
  2133
      }
deba@1024
  2134
deba@1024
  2135
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1030
  2136
        RedNode n = nodes[i];
deba@1024
  2137
        if (label == 0) {
deba@1024
  2138
          std::ostringstream os;
deba@1030
  2139
          os << _graph.id(static_cast<Node>(n));
deba@1024
  2140
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2141
          *_os << '\t';
deba@1030
  2142
          _red_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2143
        }
deba@1030
  2144
        for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2145
             it != _red_node_maps.end(); ++it) {
deba@1024
  2146
          std::string value = it->second->get(n);
deba@1024
  2147
          _writer_bits::writeToken(*_os, value);
deba@1024
  2148
          if (it->first == "label") {
deba@1030
  2149
            _red_node_index.insert(std::make_pair(n, value));
deba@1024
  2150
          }
deba@1024
  2151
          *_os << '\t';
deba@1024
  2152
        }
deba@1024
  2153
        *_os << std::endl;
deba@1024
  2154
      }
deba@1024
  2155
    }
deba@1024
  2156
deba@1024
  2157
    void writeBlueNodes() {
deba@1030
  2158
      _writer_bits::MapStorageBase<BlueNode>* label = 0;
deba@1030
  2159
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2160
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2161
        if (it->first == "label") {
deba@1024
  2162
          label = it->second;
deba@1024
  2163
          break;
deba@1024
  2164
        }
deba@1024
  2165
      }
deba@1024
  2166
deba@1024
  2167
      *_os << "@blue_nodes";
deba@1024
  2168
      if (!_nodes_caption.empty()) {
deba@1024
  2169
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@1024
  2170
      }
deba@1024
  2171
      *_os << std::endl;
deba@1024
  2172
deba@1024
  2173
      if (label == 0) {
deba@1024
  2174
        *_os << "label" << '\t';
deba@1024
  2175
      }
deba@1030
  2176
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2177
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2178
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2179
      }
deba@1024
  2180
      *_os << std::endl;
deba@1024
  2181
deba@1030
  2182
      std::vector<BlueNode> nodes;
deba@1026
  2183
      for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2184
        nodes.push_back(n);
deba@1024
  2185
      }
deba@1024
  2186
deba@1024
  2187
      if (label == 0) {
deba@1024
  2188
        IdMap<BGR, Node> id_map(_graph);
deba@1024
  2189
        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
deba@1024
  2190
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@1024
  2191
      } else {
deba@1024
  2192
        label->sort(nodes);
deba@1024
  2193
      }
deba@1024
  2194
deba@1024
  2195
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
deba@1030
  2196
        BlueNode n = nodes[i];
deba@1024
  2197
        if (label == 0) {
deba@1024
  2198
          std::ostringstream os;
deba@1030
  2199
          os << _graph.id(static_cast<Node>(n));
deba@1024
  2200
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2201
          *_os << '\t';
deba@1030
  2202
          _blue_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2203
        }
deba@1030
  2204
        for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2205
             it != _blue_node_maps.end(); ++it) {
deba@1024
  2206
          std::string value = it->second->get(n);
deba@1024
  2207
          _writer_bits::writeToken(*_os, value);
deba@1024
  2208
          if (it->first == "label") {
deba@1030
  2209
            _blue_node_index.insert(std::make_pair(n, value));
deba@1024
  2210
          }
deba@1024
  2211
          *_os << '\t';
deba@1024
  2212
        }
deba@1024
  2213
        *_os << std::endl;
deba@1024
  2214
      }
deba@1024
  2215
    }
deba@1024
  2216
deba@1024
  2217
    void createRedNodeIndex() {
deba@1030
  2218
      _writer_bits::MapStorageBase<RedNode>* label = 0;
deba@1030
  2219
      for (typename RedNodeMaps::iterator it = _red_node_maps.begin();
deba@1030
  2220
           it != _red_node_maps.end(); ++it) {
deba@1024
  2221
        if (it->first == "label") {
deba@1024
  2222
          label = it->second;
deba@1024
  2223
          break;
deba@1024
  2224
        }
deba@1024
  2225
      }
deba@1024
  2226
deba@1024
  2227
      if (label == 0) {
deba@1030
  2228
        for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2229
          std::ostringstream os;
deba@1024
  2230
          os << _graph.id(n);
deba@1030
  2231
          _red_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2232
        }
deba@1024
  2233
      } else {
deba@1030
  2234
        for (RedNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2235
          std::string value = label->get(n);
deba@1030
  2236
          _red_node_index.insert(std::make_pair(n, value));
deba@1024
  2237
        }
deba@1024
  2238
      }
deba@1024
  2239
    }
deba@1024
  2240
deba@1024
  2241
    void createBlueNodeIndex() {
deba@1030
  2242
      _writer_bits::MapStorageBase<BlueNode>* label = 0;
deba@1030
  2243
      for (typename BlueNodeMaps::iterator it = _blue_node_maps.begin();
deba@1030
  2244
           it != _blue_node_maps.end(); ++it) {
deba@1024
  2245
        if (it->first == "label") {
deba@1024
  2246
          label = it->second;
deba@1024
  2247
          break;
deba@1024
  2248
        }
deba@1024
  2249
      }
deba@1024
  2250
deba@1024
  2251
      if (label == 0) {
deba@1030
  2252
        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2253
          std::ostringstream os;
deba@1024
  2254
          os << _graph.id(n);
deba@1030
  2255
          _blue_node_index.insert(std::make_pair(n, os.str()));
deba@1024
  2256
        }
deba@1024
  2257
      } else {
deba@1030
  2258
        for (BlueNodeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2259
          std::string value = label->get(n);
deba@1030
  2260
          _blue_node_index.insert(std::make_pair(n, value));
deba@1024
  2261
        }
deba@1024
  2262
      }
deba@1024
  2263
    }
deba@1024
  2264
deba@1024
  2265
    void writeEdges() {
deba@1024
  2266
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2267
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2268
           it != _edge_maps.end(); ++it) {
deba@1024
  2269
        if (it->first == "label") {
deba@1024
  2270
          label = it->second;
deba@1024
  2271
          break;
deba@1024
  2272
        }
deba@1024
  2273
      }
deba@1024
  2274
deba@1024
  2275
      *_os << "@edges";
deba@1024
  2276
      if (!_edges_caption.empty()) {
deba@1024
  2277
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@1024
  2278
      }
deba@1024
  2279
      *_os << std::endl;
deba@1024
  2280
deba@1024
  2281
      *_os << '\t' << '\t';
deba@1024
  2282
      if (label == 0) {
deba@1024
  2283
        *_os << "label" << '\t';
deba@1024
  2284
      }
deba@1024
  2285
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2286
           it != _edge_maps.end(); ++it) {
deba@1024
  2287
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@1024
  2288
      }
deba@1024
  2289
      *_os << std::endl;
deba@1024
  2290
deba@1024
  2291
      std::vector<Edge> edges;
deba@1024
  2292
      for (EdgeIt n(_graph); n != INVALID; ++n) {
deba@1024
  2293
        edges.push_back(n);
deba@1024
  2294
      }
deba@1024
  2295
deba@1024
  2296
      if (label == 0) {
deba@1024
  2297
        IdMap<BGR, Edge> id_map(_graph);
deba@1024
  2298
        _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
deba@1024
  2299
        std::sort(edges.begin(), edges.end(), id_less);
deba@1024
  2300
      } else {
deba@1024
  2301
        label->sort(edges);
deba@1024
  2302
      }
deba@1024
  2303
deba@1024
  2304
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
deba@1024
  2305
        Edge e = edges[i];
deba@1030
  2306
        _writer_bits::writeToken(*_os, _red_node_index.
deba@1024
  2307
                                 find(_graph.redNode(e))->second);
deba@1024
  2308
        *_os << '\t';
deba@1030
  2309
        _writer_bits::writeToken(*_os, _blue_node_index.
deba@1024
  2310
                                 find(_graph.blueNode(e))->second);
deba@1024
  2311
        *_os << '\t';
deba@1024
  2312
        if (label == 0) {
deba@1024
  2313
          std::ostringstream os;
deba@1024
  2314
          os << _graph.id(e);
deba@1024
  2315
          _writer_bits::writeToken(*_os, os.str());
deba@1024
  2316
          *_os << '\t';
deba@1024
  2317
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2318
        }
deba@1024
  2319
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2320
             it != _edge_maps.end(); ++it) {
deba@1024
  2321
          std::string value = it->second->get(e);
deba@1024
  2322
          _writer_bits::writeToken(*_os, value);
deba@1024
  2323
          if (it->first == "label") {
deba@1024
  2324
            _edge_index.insert(std::make_pair(e, value));
deba@1024
  2325
          }
deba@1024
  2326
          *_os << '\t';
deba@1024
  2327
        }
deba@1024
  2328
        *_os << std::endl;
deba@1024
  2329
      }
deba@1024
  2330
    }
deba@1024
  2331
deba@1024
  2332
    void createEdgeIndex() {
deba@1024
  2333
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@1024
  2334
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
deba@1024
  2335
           it != _edge_maps.end(); ++it) {
deba@1024
  2336
        if (it->first == "label") {
deba@1024
  2337
          label = it->second;
deba@1024
  2338
          break;
deba@1024
  2339
        }
deba@1024
  2340
      }
deba@1024
  2341
deba@1024
  2342
      if (label == 0) {
deba@1024
  2343
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2344
          std::ostringstream os;
deba@1024
  2345
          os << _graph.id(e);
deba@1024
  2346
          _edge_index.insert(std::make_pair(e, os.str()));
deba@1024
  2347
        }
deba@1024
  2348
      } else {
deba@1024
  2349
        for (EdgeIt e(_graph); e != INVALID; ++e) {
deba@1024
  2350
          std::string value = label->get(e);
deba@1024
  2351
          _edge_index.insert(std::make_pair(e, value));
deba@1024
  2352
        }
deba@1024
  2353
      }
deba@1024
  2354
    }
deba@1024
  2355
deba@1024
  2356
    void writeAttributes() {
deba@1024
  2357
      if (_attributes.empty()) return;
deba@1024
  2358
      *_os << "@attributes";
deba@1024
  2359
      if (!_attributes_caption.empty()) {
deba@1024
  2360
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@1024
  2361
      }
deba@1024
  2362
      *_os << std::endl;
deba@1024
  2363
      for (typename Attributes::iterator it = _attributes.begin();
deba@1024
  2364
           it != _attributes.end(); ++it) {
deba@1024
  2365
        _writer_bits::writeToken(*_os, it->first) << ' ';
deba@1024
  2366
        _writer_bits::writeToken(*_os, it->second->get());
deba@1024
  2367
        *_os << std::endl;
deba@1024
  2368
      }
deba@1024
  2369
    }
deba@1024
  2370
deba@1024
  2371
  public:
deba@1024
  2372
deba@1024
  2373
    /// \name Execution of the Writer
deba@1024
  2374
    /// @{
deba@1024
  2375
deba@1024
  2376
    /// \brief Start the batch processing
deba@1024
  2377
    ///
deba@1024
  2378
    /// This function starts the batch processing.
deba@1024
  2379
    void run() {
deba@1024
  2380
      if (!_skip_nodes) {
deba@1024
  2381
        writeRedNodes();
deba@1024
  2382
        writeBlueNodes();
deba@1024
  2383
      } else {
deba@1024
  2384
        createRedNodeIndex();
deba@1024
  2385
        createBlueNodeIndex();
deba@1024
  2386
      }
deba@1024
  2387
      if (!_skip_edges) {
deba@1024
  2388
        writeEdges();
deba@1024
  2389
      } else {
deba@1024
  2390
        createEdgeIndex();
deba@1024
  2391
      }
deba@1024
  2392
      writeAttributes();
deba@1024
  2393
    }
deba@1024
  2394
deba@1024
  2395
    /// \brief Give back the stream of the writer
deba@1024
  2396
    ///
deba@1024
  2397
    /// Give back the stream of the writer
deba@1024
  2398
    std::ostream& ostream() {
deba@1024
  2399
      return *_os;
deba@1024
  2400
    }
deba@1024
  2401
deba@1024
  2402
    /// @}
deba@1024
  2403
  };
deba@1024
  2404
deba@1024
  2405
  /// \ingroup lemon_io
deba@1024
  2406
  ///
alpar@1076
  2407
  /// \brief Return a \ref lemon::BpGraphWriter "BpGraphWriter" class
deba@1024
  2408
  ///
alpar@1076
  2409
  /// This function just returns a \ref lemon::BpGraphWriter
alpar@1076
  2410
  /// "BpGraphWriter" class.
deba@1024
  2411
  ///
deba@1024
  2412
  /// With this function a bipartite graph can be write to a file or output
deba@1024
  2413
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@1024
  2414
  /// attributes. For example, with the following code a bipartite
deba@1024
  2415
  /// weighted matching problem can be written to the standard output,
deba@1024
  2416
  /// i.e. a graph with a \e weight map on the edges:
deba@1024
  2417
  ///
deba@1024
  2418
  ///\code
deba@1024
  2419
  ///ListBpGraph graph;
deba@1024
  2420
  ///ListBpGraph::EdgeMap<int> weight(graph);
deba@1024
  2421
  ///  // Setting the weight map
deba@1024
  2422
  ///bpGraphWriter(graph, std::cout).
deba@1024
  2423
  ///  edgeMap("weight", weight).
deba@1024
  2424
  ///  run();
deba@1024
  2425
  ///\endcode
deba@1024
  2426
  ///
alpar@1076
  2427
  /// For a complete documentation, please see the
alpar@1076
  2428
  /// \ref lemon::BpGraphWriter "BpGraphWriter"
deba@1024
  2429
  /// class documentation.
alpar@1076
  2430
  /// \warning Don't forget to put the \ref lemon::BpGraphWriter::run() "run()"
deba@1024
  2431
  /// to the end of the parameter list.
deba@1024
  2432
  /// \relates BpGraphWriter
deba@1024
  2433
  /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
deba@1024
  2434
  /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
deba@1024
  2435
  template <typename TBGR>
deba@1024
  2436
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
deba@1024
  2437
    BpGraphWriter<TBGR> tmp(graph, os);
deba@1024
  2438
    return tmp;
deba@1024
  2439
  }
deba@1024
  2440
deba@1024
  2441
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2442
  ///
deba@1024
  2443
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2444
  /// \relates BpGraphWriter
deba@1024
  2445
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2446
  template <typename TBGR>
deba@1024
  2447
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
deba@1024
  2448
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2449
    return tmp;
deba@1024
  2450
  }
deba@1024
  2451
deba@1024
  2452
  /// \brief Return a \ref BpGraphWriter class
deba@1024
  2453
  ///
deba@1024
  2454
  /// This function just returns a \ref BpGraphWriter class.
deba@1024
  2455
  /// \relates BpGraphWriter
deba@1024
  2456
  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
deba@1024
  2457
  template <typename TBGR>
deba@1024
  2458
  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
deba@1024
  2459
    BpGraphWriter<TBGR> tmp(graph, fn);
deba@1024
  2460
    return tmp;
deba@1024
  2461
  }
deba@1024
  2462
deba@248
  2463
  class SectionWriter;
deba@248
  2464
deba@248
  2465
  SectionWriter sectionWriter(std::istream& is);
deba@248
  2466
  SectionWriter sectionWriter(const std::string& fn);
deba@248
  2467
  SectionWriter sectionWriter(const char* fn);
deba@248
  2468
deba@248
  2469
  /// \ingroup lemon_io
deba@248
  2470
  ///
deba@248
  2471
  /// \brief Section writer class
deba@248
  2472
  ///
deba@248
  2473
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
deba@248
  2474
  /// which contain any data in arbitrary format. Such sections can be
deba@248
  2475
  /// written with this class. A writing rule can be added to the
deba@248
  2476
  /// class with two different functions. With the \c sectionLines()
deba@248
  2477
  /// function a generator can write the section line-by-line, while
deba@248
  2478
  /// with the \c sectionStream() member the section can be written to
deba@248
  2479
  /// an output stream.
deba@248
  2480
  class SectionWriter {
deba@248
  2481
  private:
deba@248
  2482
deba@248
  2483
    std::ostream* _os;
deba@248
  2484
    bool local_os;
deba@248
  2485
deba@248
  2486
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
deba@248
  2487
    Sections;
deba@248
  2488
deba@248
  2489
    Sections _sections;
deba@248
  2490
deba@248
  2491
  public:
deba@248
  2492
deba@248
  2493
    /// \brief Constructor
deba@248
  2494
    ///
deba@248
  2495
    /// Construct a section writer, which writes to the given output
deba@248
  2496
    /// stream.
deba@248
  2497
    SectionWriter(std::ostream& os)
deba@248
  2498
      : _os(&os), local_os(false) {}
deba@248
  2499
deba@248
  2500
    /// \brief Constructor
deba@248
  2501
    ///
deba@248
  2502
    /// Construct a section writer, which writes into the given file.
deba@248
  2503
    SectionWriter(const std::string& fn)
deba@290
  2504
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
deba@295
  2505
      if (!(*_os)) {
deba@295
  2506
        delete _os;
deba@295
  2507
        throw IoError("Cannot write file", fn);
deba@295
  2508
      }
deba@290
  2509
    }
deba@248
  2510
deba@248
  2511
    /// \brief Constructor
deba@248
  2512
    ///
deba@248
  2513
    /// Construct a section writer, which writes into the given file.
deba@248
  2514
    SectionWriter(const char* fn)
deba@290
  2515
      : _os(new std::ofstream(fn)), local_os(true) {
deba@295
  2516
      if (!(*_os)) {
deba@295
  2517
        delete _os;
deba@295
  2518
        throw IoError("Cannot write file", fn);
deba@295
  2519
      }
deba@290
  2520
    }
deba@248
  2521
deba@248
  2522
    /// \brief Destructor
deba@248
  2523
    ~SectionWriter() {
deba@248
  2524
      for (Sections::iterator it = _sections.begin();
deba@248
  2525
           it != _sections.end(); ++it) {
deba@248
  2526
        delete it->second;
deba@248
  2527
      }
deba@248
  2528
deba@248
  2529
      if (local_os) {
deba@248
  2530
        delete _os;
deba@248
  2531
      }
deba@248
  2532
deba@248
  2533
    }
deba@248
  2534
deba@248
  2535
  private:
deba@248
  2536
deba@248
  2537
    friend SectionWriter sectionWriter(std::ostream& os);
deba@248
  2538
    friend SectionWriter sectionWriter(const std::string& fn);
deba@248
  2539
    friend SectionWriter sectionWriter(const char* fn);
deba@248
  2540
deba@248
  2541
    SectionWriter(SectionWriter& other)
deba@248
  2542
      : _os(other._os), local_os(other.local_os) {
deba@248
  2543
deba@248
  2544
      other._os = 0;
deba@248
  2545
      other.local_os = false;
deba@248
  2546
deba@248
  2547
      _sections.swap(other._sections);
deba@248
  2548
    }
deba@248
  2549
deba@248
  2550
    SectionWriter& operator=(const SectionWriter&);
deba@248
  2551
deba@248
  2552
  public:
deba@248
  2553
kpeter@584
  2554
    /// \name Section Writers
deba@248
  2555
    /// @{
deba@248
  2556
deba@248
  2557
    /// \brief Add a section writer with line oriented writing
deba@248
  2558
    ///
deba@248
  2559
    /// The first parameter is the type descriptor of the section, the
deba@248
  2560
    /// second is a generator with std::string values. At the writing
deba@248
  2561
    /// process, the returned \c std::string will be written into the
deba@248
  2562
    /// output file until it is an empty string.
deba@248
  2563
    ///
deba@248
  2564
    /// For example, an integer vector is written into a section.
deba@248
  2565
    ///\code
deba@248
  2566
    ///  @numbers
deba@248
  2567
    ///  12 45 23 78
deba@248
  2568
    ///  4 28 38 28
deba@248
  2569
    ///  23 6 16
deba@248
  2570
    ///\endcode
deba@248
  2571
    ///
deba@248
  2572
    /// The generator is implemented as a struct.
deba@248
  2573
    ///\code
deba@248
  2574
    ///  struct NumberSection {
deba@248
  2575
    ///    std::vector<int>::const_iterator _it, _end;
deba@248
  2576
    ///    NumberSection(const std::vector<int>& data)
deba@248
  2577
    ///      : _it(data.begin()), _end(data.end()) {}
deba@248
  2578
    ///    std::string operator()() {
deba@248
  2579
    ///      int rem_in_line = 4;
deba@248
  2580
    ///      std::ostringstream ls;
deba@248
  2581
    ///      while (rem_in_line > 0 && _it != _end) {
deba@248
  2582
    ///        ls << *(_it++) << ' ';
deba@248
  2583
    ///        --rem_in_line;
deba@248
  2584
    ///      }
deba@248
  2585
    ///      return ls.str();
deba@248
  2586
    ///    }
deba@248
  2587
    ///  };
deba@248
  2588
    ///
deba@248
  2589
    ///  // ...
deba@248
  2590
    ///
deba@248
  2591
    ///  writer.sectionLines("numbers", NumberSection(vec));
deba@248
  2592
    ///\endcode
deba@248
  2593
    template <typename Functor>
deba@248
  2594
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
deba@248
  2595
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2596
      _sections.push_back(std::make_pair(type,
deba@248
  2597
        new _writer_bits::LineSection<Functor>(functor)));
deba@248
  2598
      return *this;
deba@248
  2599
    }
deba@248
  2600
deba@248
  2601
deba@248
  2602
    /// \brief Add a section writer with stream oriented writing
deba@248
  2603
    ///
deba@248
  2604
    /// The first parameter is the type of the section, the second is
deba@248
  2605
    /// a functor, which takes a \c std::ostream& parameter. The
deba@248
  2606
    /// functor writes the section to the output stream.
deba@248
  2607
    /// \warning The last line must be closed with end-line character.
deba@248
  2608
    template <typename Functor>
deba@248
  2609
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
deba@248
  2610
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  2611
      _sections.push_back(std::make_pair(type,
deba@248
  2612
         new _writer_bits::StreamSection<Functor>(functor)));
deba@248
  2613
      return *this;
deba@248
  2614
    }
deba@248
  2615
deba@248
  2616
    /// @}
deba@248
  2617
deba@248
  2618
  public:
deba@248
  2619
deba@248
  2620
kpeter@584
  2621
    /// \name Execution of the Writer
deba@248
  2622
    /// @{
deba@248
  2623
deba@248
  2624
    /// \brief Start the batch processing
deba@248
  2625
    ///
deba@248
  2626
    /// This function starts the batch processing.
deba@248
  2627
    void run() {
deba@248
  2628
deba@248
  2629
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
deba@248
  2630
deba@248
  2631
      for (Sections::iterator it = _sections.begin();
deba@248
  2632
           it != _sections.end(); ++it) {
deba@248
  2633
        (*_os) << '@' << it->first << std::endl;
deba@248
  2634
        it->second->process(*_os);
deba@248
  2635
      }
deba@248
  2636
    }
deba@248
  2637
deba@248
  2638
    /// \brief Give back the stream of the writer
deba@248
  2639
    ///
deba@248
  2640
    /// Returns the stream of the writer
deba@248
  2641
    std::ostream& ostream() {
deba@248
  2642
      return *_os;
deba@248
  2643
    }
deba@248
  2644
deba@248
  2645
    /// @}
deba@248
  2646
deba@248
  2647
  };
deba@248
  2648
deba@598
  2649
  /// \ingroup lemon_io
deba@598
  2650
  ///
deba@248
  2651
  /// \brief Return a \ref SectionWriter class
deba@248
  2652
  ///
deba@248
  2653
  /// This function just returns a \ref SectionWriter class.
deba@598
  2654
  ///
deba@598
  2655
  /// Please see SectionWriter documentation about the custom section
deba@598
  2656
  /// output.
deba@598
  2657
  ///
deba@248
  2658
  /// \relates SectionWriter
deba@598
  2659
  /// \sa sectionWriter(const std::string& fn)
deba@598
  2660
  /// \sa sectionWriter(const char *fn)
deba@248
  2661
  inline SectionWriter sectionWriter(std::ostream& os) {
deba@248
  2662
    SectionWriter tmp(os);
deba@248
  2663
    return tmp;
deba@248
  2664
  }
deba@248
  2665
deba@248
  2666
  /// \brief Return a \ref SectionWriter class
deba@248
  2667
  ///
deba@248
  2668
  /// This function just returns a \ref SectionWriter class.
deba@248
  2669
  /// \relates SectionWriter
deba@598
  2670
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2671
  inline SectionWriter sectionWriter(const std::string& fn) {
deba@248
  2672
    SectionWriter tmp(fn);
deba@248
  2673
    return tmp;
deba@248
  2674
  }
deba@248
  2675
deba@248
  2676
  /// \brief Return a \ref SectionWriter class
deba@248
  2677
  ///
deba@248
  2678
  /// This function just returns a \ref SectionWriter class.
deba@248
  2679
  /// \relates SectionWriter
deba@598
  2680
  /// \sa sectionWriter(std::ostream& os)
deba@248
  2681
  inline SectionWriter sectionWriter(const char* fn) {
deba@248
  2682
    SectionWriter tmp(fn);
deba@248
  2683
    return tmp;
deba@248
  2684
  }
deba@127
  2685
}
deba@127
  2686
deba@127
  2687
#endif