lemon/lgf_writer.h
author Balazs Dezso <deba@inf.elte.hu>
Thu, 24 Jun 2010 09:27:53 +0200
changeset 982 bb70ad62c95f
parent 645 a3402913cffe
parent 631 33c6b6e755cd
child 956 141f9c0db4a3
child 1081 f1398882a928
permissions -rw-r--r--
Fix critical bug in preflow (#372)

The wrong transition between the bound decrease and highest active
heuristics caused the bug. The last node chosen in bound decrease mode
is used in the first iteration in highest active mode.
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@463
     5
 * Copyright (C) 2003-2009
deba@127
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@127
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@127
     8
 *
deba@127
     9
 * Permission to use, modify and distribute this software is granted
deba@127
    10
 * provided that this copyright notice appears in all copies. For
deba@127
    11
 * precise terms see the accompanying LICENSE file.
deba@127
    12
 *
deba@127
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@127
    14
 * express or implied, and with no claim as to its suitability for any
deba@127
    15
 * purpose.
deba@127
    16
 *
deba@127
    17
 */
deba@127
    18
deba@127
    19
///\ingroup lemon_io
deba@127
    20
///\file
ladanyi@236
    21
///\brief \ref lgf-format "LEMON Graph Format" writer.
deba@127
    22
deba@127
    23
deba@127
    24
#ifndef LEMON_LGF_WRITER_H
deba@127
    25
#define LEMON_LGF_WRITER_H
deba@127
    26
deba@127
    27
#include <iostream>
deba@127
    28
#include <fstream>
deba@127
    29
#include <sstream>
deba@127
    30
deba@127
    31
#include <algorithm>
deba@127
    32
deba@127
    33
#include <vector>
deba@127
    34
#include <functional>
deba@127
    35
deba@220
    36
#include <lemon/core.h>
deba@220
    37
#include <lemon/maps.h>
deba@127
    38
deba@248
    39
#include <lemon/concept_check.h>
deba@248
    40
#include <lemon/concepts/maps.h>
deba@248
    41
deba@127
    42
namespace lemon {
deba@127
    43
deba@127
    44
  namespace _writer_bits {
deba@127
    45
deba@127
    46
    template <typename Value>
deba@127
    47
    struct DefaultConverter {
deba@127
    48
      std::string operator()(const Value& value) {
alpar@209
    49
        std::ostringstream os;
alpar@209
    50
        os << value;
alpar@209
    51
        return os.str();
deba@127
    52
      }
deba@127
    53
    };
deba@127
    54
deba@127
    55
    template <typename T>
deba@127
    56
    bool operator<(const T&, const T&) {
deba@290
    57
      throw FormatError("Label map is not comparable");
deba@127
    58
    }
deba@127
    59
deba@127
    60
    template <typename _Map>
deba@127
    61
    class MapLess {
deba@127
    62
    public:
deba@127
    63
      typedef _Map Map;
deba@127
    64
      typedef typename Map::Key Item;
deba@127
    65
deba@127
    66
    private:
deba@127
    67
      const Map& _map;
alpar@209
    68
deba@127
    69
    public:
deba@127
    70
      MapLess(const Map& map) : _map(map) {}
deba@127
    71
deba@127
    72
      bool operator()(const Item& left, const Item& right) {
alpar@209
    73
        return _map[left] < _map[right];
deba@127
    74
      }
deba@127
    75
    };
deba@127
    76
deba@165
    77
    template <typename _Graph, bool _dir, typename _Map>
deba@165
    78
    class GraphArcMapLess {
deba@165
    79
    public:
deba@165
    80
      typedef _Map Map;
deba@165
    81
      typedef _Graph Graph;
deba@165
    82
      typedef typename Graph::Edge Item;
deba@165
    83
deba@165
    84
    private:
deba@165
    85
      const Graph& _graph;
deba@165
    86
      const Map& _map;
alpar@209
    87
deba@165
    88
    public:
alpar@209
    89
      GraphArcMapLess(const Graph& graph, const Map& map)
alpar@209
    90
        : _graph(graph), _map(map) {}
deba@165
    91
deba@165
    92
      bool operator()(const Item& left, const Item& right) {
alpar@209
    93
        return _map[_graph.direct(left, _dir)] <
alpar@209
    94
          _map[_graph.direct(right, _dir)];
deba@165
    95
      }
deba@165
    96
    };
deba@165
    97
alpar@209
    98
    template <typename _Item>
deba@127
    99
    class MapStorageBase {
deba@127
   100
    public:
deba@127
   101
      typedef _Item Item;
deba@127
   102
deba@127
   103
    public:
deba@127
   104
      MapStorageBase() {}
deba@127
   105
      virtual ~MapStorageBase() {}
deba@127
   106
deba@127
   107
      virtual std::string get(const Item& item) = 0;
deba@127
   108
      virtual void sort(std::vector<Item>&) = 0;
deba@127
   109
    };
deba@127
   110
alpar@209
   111
    template <typename _Item, typename _Map,
alpar@209
   112
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@127
   113
    class MapStorage : public MapStorageBase<_Item> {
deba@127
   114
    public:
deba@127
   115
      typedef _Map Map;
deba@127
   116
      typedef _Converter Converter;
deba@127
   117
      typedef _Item Item;
alpar@209
   118
deba@127
   119
    private:
deba@127
   120
      const Map& _map;
deba@127
   121
      Converter _converter;
deba@127
   122
deba@127
   123
    public:
alpar@209
   124
      MapStorage(const Map& map, const Converter& converter = Converter())
alpar@209
   125
        : _map(map), _converter(converter) {}
deba@127
   126
      virtual ~MapStorage() {}
deba@127
   127
deba@127
   128
      virtual std::string get(const Item& item) {
alpar@209
   129
        return _converter(_map[item]);
deba@127
   130
      }
deba@127
   131
      virtual void sort(std::vector<Item>& items) {
alpar@209
   132
        MapLess<Map> less(_map);
alpar@209
   133
        std::sort(items.begin(), items.end(), less);
deba@127
   134
      }
deba@127
   135
    };
deba@127
   136
alpar@209
   137
    template <typename _Graph, bool _dir, typename _Map,
alpar@209
   138
              typename _Converter = DefaultConverter<typename _Map::Value> >
deba@165
   139
    class GraphArcMapStorage : public MapStorageBase<typename _Graph::Edge> {
deba@165
   140
    public:
deba@165
   141
      typedef _Map Map;
deba@165
   142
      typedef _Converter Converter;
deba@165
   143
      typedef _Graph Graph;
deba@165
   144
      typedef typename Graph::Edge Item;
deba@165
   145
      static const bool dir = _dir;
alpar@209
   146
deba@165
   147
    private:
deba@165
   148
      const Graph& _graph;
deba@165
   149
      const Map& _map;
deba@165
   150
      Converter _converter;
deba@165
   151
deba@165
   152
    public:
alpar@209
   153
      GraphArcMapStorage(const Graph& graph, const Map& map,
alpar@209
   154
                         const Converter& converter = Converter())
alpar@209
   155
        : _graph(graph), _map(map), _converter(converter) {}
deba@165
   156
      virtual ~GraphArcMapStorage() {}
deba@165
   157
deba@165
   158
      virtual std::string get(const Item& item) {
alpar@209
   159
        return _converter(_map[_graph.direct(item, dir)]);
deba@165
   160
      }
deba@165
   161
      virtual void sort(std::vector<Item>& items) {
alpar@209
   162
        GraphArcMapLess<Graph, dir, Map> less(_graph, _map);
alpar@209
   163
        std::sort(items.begin(), items.end(), less);
deba@165
   164
      }
deba@165
   165
    };
deba@165
   166
deba@127
   167
    class ValueStorageBase {
deba@127
   168
    public:
deba@127
   169
      ValueStorageBase() {}
deba@127
   170
      virtual ~ValueStorageBase() {}
deba@127
   171
alpar@209
   172
      virtual std::string get() = 0;
deba@127
   173
    };
deba@127
   174
deba@127
   175
    template <typename _Value, typename _Converter = DefaultConverter<_Value> >
deba@127
   176
    class ValueStorage : public ValueStorageBase {
deba@127
   177
    public:
deba@127
   178
      typedef _Value Value;
deba@127
   179
      typedef _Converter Converter;
deba@127
   180
deba@127
   181
    private:
deba@127
   182
      const Value& _value;
deba@127
   183
      Converter _converter;
deba@127
   184
deba@127
   185
    public:
deba@127
   186
      ValueStorage(const Value& value, const Converter& converter = Converter())
kpeter@212
   187
        : _value(value), _converter(converter) {}
deba@127
   188
deba@127
   189
      virtual std::string get() {
alpar@209
   190
        return _converter(_value);
deba@127
   191
      }
deba@127
   192
    };
deba@127
   193
deba@127
   194
    template <typename Value>
deba@127
   195
    struct MapLookUpConverter {
deba@127
   196
      const std::map<Value, std::string>& _map;
alpar@209
   197
alpar@209
   198
      MapLookUpConverter(const std::map<Value, std::string>& map)
alpar@209
   199
        : _map(map) {}
alpar@209
   200
deba@127
   201
      std::string operator()(const Value& str) {
alpar@209
   202
        typename std::map<Value, std::string>::const_iterator it =
alpar@209
   203
          _map.find(str);
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@165
   211
    template <typename Graph>
deba@165
   212
    struct GraphArcLookUpConverter {
deba@165
   213
      const Graph& _graph;
deba@165
   214
      const std::map<typename Graph::Edge, std::string>& _map;
alpar@209
   215
alpar@209
   216
      GraphArcLookUpConverter(const Graph& graph,
alpar@209
   217
                              const std::map<typename Graph::Edge,
alpar@209
   218
                                             std::string>& map)
alpar@209
   219
        : _graph(graph), _map(map) {}
alpar@209
   220
deba@165
   221
      std::string operator()(const typename Graph::Arc& val) {
alpar@209
   222
        typename std::map<typename Graph::Edge, std::string>
alpar@209
   223
          ::const_iterator it = _map.find(val);
alpar@209
   224
        if (it == _map.end()) {
deba@290
   225
          throw FormatError("Item not found");
alpar@209
   226
        }
alpar@209
   227
        return (_graph.direction(val) ? '+' : '-') + it->second;
deba@165
   228
      }
deba@165
   229
    };
deba@165
   230
deba@197
   231
    inline bool isWhiteSpace(char c) {
alpar@209
   232
      return c == ' ' || c == '\t' || c == '\v' ||
alpar@209
   233
        c == '\n' || c == '\r' || c == '\f';
deba@127
   234
    }
deba@127
   235
deba@197
   236
    inline bool isEscaped(char c) {
alpar@209
   237
      return c == '\\' || c == '\"' || c == '\'' ||
alpar@209
   238
        c == '\a' || c == '\b';
deba@127
   239
    }
deba@127
   240
deba@197
   241
    inline static void writeEscape(std::ostream& os, char c) {
deba@127
   242
      switch (c) {
deba@127
   243
      case '\\':
alpar@209
   244
        os << "\\\\";
alpar@209
   245
        return;
deba@127
   246
      case '\"':
alpar@209
   247
        os << "\\\"";
alpar@209
   248
        return;
deba@127
   249
      case '\a':
alpar@209
   250
        os << "\\a";
alpar@209
   251
        return;
deba@127
   252
      case '\b':
alpar@209
   253
        os << "\\b";
alpar@209
   254
        return;
deba@127
   255
      case '\f':
alpar@209
   256
        os << "\\f";
alpar@209
   257
        return;
deba@127
   258
      case '\r':
alpar@209
   259
        os << "\\r";
alpar@209
   260
        return;
deba@127
   261
      case '\n':
alpar@209
   262
        os << "\\n";
alpar@209
   263
        return;
deba@127
   264
      case '\t':
alpar@209
   265
        os << "\\t";
alpar@209
   266
        return;
deba@127
   267
      case '\v':
alpar@209
   268
        os << "\\v";
alpar@209
   269
        return;
deba@127
   270
      default:
alpar@209
   271
        if (c < 0x20) {
alpar@209
   272
          std::ios::fmtflags flags = os.flags();
alpar@209
   273
          os << '\\' << std::oct << static_cast<int>(c);
alpar@209
   274
          os.flags(flags);
alpar@209
   275
        } else {
alpar@209
   276
          os << c;
alpar@209
   277
        }
alpar@209
   278
        return;
alpar@209
   279
      }
deba@127
   280
    }
deba@127
   281
deba@197
   282
    inline bool requireEscape(const std::string& str) {
alpar@156
   283
      if (str.empty() || str[0] == '@') return true;
deba@127
   284
      std::istringstream is(str);
deba@127
   285
      char c;
deba@127
   286
      while (is.get(c)) {
alpar@209
   287
        if (isWhiteSpace(c) || isEscaped(c)) {
alpar@209
   288
          return true;
alpar@209
   289
        }
deba@127
   290
      }
deba@127
   291
      return false;
deba@127
   292
    }
alpar@209
   293
deba@197
   294
    inline std::ostream& writeToken(std::ostream& os, const std::string& str) {
deba@127
   295
deba@127
   296
      if (requireEscape(str)) {
alpar@209
   297
        os << '\"';
alpar@209
   298
        for (std::string::const_iterator it = str.begin();
alpar@209
   299
             it != str.end(); ++it) {
alpar@209
   300
          writeEscape(os, *it);
alpar@209
   301
        }
alpar@209
   302
        os << '\"';
deba@127
   303
      } else {
alpar@209
   304
        os << str;
deba@127
   305
      }
deba@127
   306
      return os;
deba@127
   307
    }
deba@127
   308
deba@248
   309
    class Section {
deba@248
   310
    public:
deba@248
   311
      virtual ~Section() {}
deba@248
   312
      virtual void process(std::ostream& os) = 0;
deba@248
   313
    };
deba@248
   314
deba@248
   315
    template <typename Functor>
deba@248
   316
    class LineSection : public Section {
deba@248
   317
    private:
deba@248
   318
deba@248
   319
      Functor _functor;
deba@248
   320
deba@248
   321
    public:
deba@248
   322
deba@248
   323
      LineSection(const Functor& functor) : _functor(functor) {}
deba@248
   324
      virtual ~LineSection() {}
deba@248
   325
deba@248
   326
      virtual void process(std::ostream& os) {
deba@248
   327
        std::string line;
deba@248
   328
        while (!(line = _functor()).empty()) os << line << std::endl;
deba@248
   329
      }
deba@248
   330
    };
deba@248
   331
deba@248
   332
    template <typename Functor>
deba@248
   333
    class StreamSection : public Section {
deba@248
   334
    private:
deba@248
   335
deba@248
   336
      Functor _functor;
deba@248
   337
deba@248
   338
    public:
deba@248
   339
deba@248
   340
      StreamSection(const Functor& functor) : _functor(functor) {}
deba@248
   341
      virtual ~StreamSection() {}
deba@248
   342
deba@248
   343
      virtual void process(std::ostream& os) {
deba@248
   344
        _functor(os);
deba@248
   345
      }
deba@248
   346
    };
deba@248
   347
deba@127
   348
  }
deba@190
   349
deba@645
   350
  template <typename DGR>
deba@190
   351
  class DigraphWriter;
deba@190
   352
deba@645
   353
  template <typename TDGR>
deba@645
   354
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
deba@645
   355
                                   std::ostream& os = std::cout);
deba@645
   356
  template <typename TDGR>
deba@645
   357
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const std::string& fn);
deba@190
   358
deba@645
   359
  template <typename TDGR>
deba@645
   360
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn);
kpeter@517
   361
alpar@209
   362
alpar@156
   363
  /// \ingroup lemon_io
alpar@209
   364
  ///
kpeter@192
   365
  /// \brief \ref lgf-format "LGF" writer for directed graphs
alpar@156
   366
  ///
alpar@156
   367
  /// This utility writes an \ref lgf-format "LGF" file.
alpar@156
   368
  ///
alpar@156
   369
  /// The writing method does a batch processing. The user creates a
alpar@156
   370
  /// writer object, then various writing rules can be added to the
alpar@156
   371
  /// writer, and eventually the writing is executed with the \c run()
alpar@156
   372
  /// member function. A map writing rule can be added to the writer
alpar@156
   373
  /// with the \c nodeMap() or \c arcMap() members. An optional
deba@163
   374
  /// converter parameter can also be added as a standard functor
kpeter@192
   375
  /// converting from the value type of the map to \c std::string. If it
kpeter@192
   376
  /// is set, it will determine how the value type of the map is written to
deba@163
   377
  /// the output stream. If the functor is not set, then a default
deba@163
   378
  /// conversion will be used. The \c attribute(), \c node() and \c
deba@163
   379
  /// arc() functions are used to add attribute writing rules.
alpar@156
   380
  ///
alpar@156
   381
  ///\code
deba@645
   382
  /// DigraphWriter<DGR>(digraph, std::cout).
kpeter@192
   383
  ///   nodeMap("coordinates", coord_map).
kpeter@192
   384
  ///   nodeMap("size", size).
kpeter@192
   385
  ///   nodeMap("title", title).
kpeter@192
   386
  ///   arcMap("capacity", cap_map).
kpeter@192
   387
  ///   node("source", src).
kpeter@192
   388
  ///   node("target", trg).
kpeter@192
   389
  ///   attribute("caption", caption).
kpeter@192
   390
  ///   run();
alpar@156
   391
  ///\endcode
alpar@156
   392
  ///
alpar@156
   393
  ///
alpar@156
   394
  /// By default, the writer does not write additional captions to the
alpar@156
   395
  /// sections, but they can be give as an optional parameter of
alpar@156
   396
  /// the \c nodes(), \c arcs() or \c
alpar@156
   397
  /// attributes() functions.
alpar@156
   398
  ///
alpar@156
   399
  /// The \c skipNodes() and \c skipArcs() functions forbid the
deba@163
   400
  /// writing of the sections. If two arc sections should be written
deba@163
   401
  /// to the output, it can be done in two passes, the first pass
deba@163
   402
  /// writes the node section and the first arc section, then the
deba@163
   403
  /// second pass skips the node section and writes just the arc
deba@163
   404
  /// section to the stream. The output stream can be retrieved with
deba@163
   405
  /// the \c ostream() function, hence the second pass can append its
deba@163
   406
  /// output to the output of the first pass.
deba@645
   407
  template <typename DGR>
deba@127
   408
  class DigraphWriter {
deba@127
   409
  public:
deba@127
   410
deba@645
   411
    typedef DGR Digraph;
deba@645
   412
    TEMPLATE_DIGRAPH_TYPEDEFS(DGR);
alpar@209
   413
deba@127
   414
  private:
deba@127
   415
deba@127
   416
deba@127
   417
    std::ostream* _os;
deba@127
   418
    bool local_os;
deba@127
   419
deba@645
   420
    const DGR& _digraph;
deba@127
   421
deba@127
   422
    std::string _nodes_caption;
deba@127
   423
    std::string _arcs_caption;
deba@127
   424
    std::string _attributes_caption;
alpar@209
   425
deba@127
   426
    typedef std::map<Node, std::string> NodeIndex;
deba@127
   427
    NodeIndex _node_index;
deba@127
   428
    typedef std::map<Arc, std::string> ArcIndex;
deba@127
   429
    ArcIndex _arc_index;
deba@127
   430
alpar@209
   431
    typedef std::vector<std::pair<std::string,
alpar@209
   432
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
   433
    NodeMaps _node_maps;
deba@127
   434
alpar@209
   435
    typedef std::vector<std::pair<std::string,
deba@127
   436
      _writer_bits::MapStorageBase<Arc>* > >ArcMaps;
deba@127
   437
    ArcMaps _arc_maps;
deba@127
   438
alpar@209
   439
    typedef std::vector<std::pair<std::string,
deba@127
   440
      _writer_bits::ValueStorageBase*> > Attributes;
deba@127
   441
    Attributes _attributes;
deba@127
   442
deba@127
   443
    bool _skip_nodes;
deba@127
   444
    bool _skip_arcs;
deba@127
   445
deba@127
   446
  public:
deba@127
   447
alpar@156
   448
    /// \brief Constructor
alpar@156
   449
    ///
alpar@156
   450
    /// Construct a directed graph writer, which writes to the given
alpar@156
   451
    /// output stream.
deba@645
   452
    DigraphWriter(const DGR& digraph, std::ostream& os = std::cout)
kpeter@293
   453
      : _os(&os), local_os(false), _digraph(digraph),
alpar@209
   454
        _skip_nodes(false), _skip_arcs(false) {}
deba@127
   455
alpar@156
   456
    /// \brief Constructor
alpar@156
   457
    ///
alpar@156
   458
    /// Construct a directed graph writer, which writes to the given
alpar@156
   459
    /// output file.
deba@645
   460
    DigraphWriter(const DGR& digraph, const std::string& fn)
deba@127
   461
      : _os(new std::ofstream(fn.c_str())), local_os(true), _digraph(digraph),
deba@290
   462
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   463
      if (!(*_os)) {
deba@295
   464
        delete _os;
deba@295
   465
        throw IoError("Cannot write file", fn);
deba@295
   466
      }
deba@290
   467
    }
deba@127
   468
alpar@156
   469
    /// \brief Constructor
alpar@156
   470
    ///
alpar@156
   471
    /// Construct a directed graph writer, which writes to the given
alpar@156
   472
    /// output file.
deba@645
   473
    DigraphWriter(const DGR& digraph, const char* fn)
deba@127
   474
      : _os(new std::ofstream(fn)), local_os(true), _digraph(digraph),
deba@290
   475
        _skip_nodes(false), _skip_arcs(false) {
deba@295
   476
      if (!(*_os)) {
deba@295
   477
        delete _os;
deba@295
   478
        throw IoError("Cannot write file", fn);
deba@295
   479
      }
deba@290
   480
    }
deba@127
   481
alpar@156
   482
    /// \brief Destructor
deba@127
   483
    ~DigraphWriter() {
alpar@209
   484
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   485
           it != _node_maps.end(); ++it) {
alpar@209
   486
        delete it->second;
deba@127
   487
      }
deba@127
   488
alpar@209
   489
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   490
           it != _arc_maps.end(); ++it) {
alpar@209
   491
        delete it->second;
deba@127
   492
      }
deba@127
   493
alpar@209
   494
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   495
           it != _attributes.end(); ++it) {
alpar@209
   496
        delete it->second;
deba@127
   497
      }
deba@127
   498
deba@127
   499
      if (local_os) {
alpar@209
   500
        delete _os;
deba@127
   501
      }
deba@127
   502
    }
deba@127
   503
deba@127
   504
  private:
deba@190
   505
deba@645
   506
    template <typename TDGR>
deba@645
   507
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
deba@645
   508
                                             std::ostream& os);
deba@645
   509
    template <typename TDGR>
deba@645
   510
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@645
   511
                                             const std::string& fn);
deba@645
   512
    template <typename TDGR>
deba@645
   513
    friend DigraphWriter<TDGR> digraphWriter(const TDGR& digraph,
deba@645
   514
                                             const char *fn);
deba@190
   515
alpar@209
   516
    DigraphWriter(DigraphWriter& other)
deba@190
   517
      : _os(other._os), local_os(other.local_os), _digraph(other._digraph),
alpar@209
   518
        _skip_nodes(other._skip_nodes), _skip_arcs(other._skip_arcs) {
deba@190
   519
deba@190
   520
      other._os = 0;
deba@190
   521
      other.local_os = false;
deba@190
   522
deba@190
   523
      _node_index.swap(other._node_index);
deba@190
   524
      _arc_index.swap(other._arc_index);
deba@190
   525
deba@190
   526
      _node_maps.swap(other._node_maps);
deba@190
   527
      _arc_maps.swap(other._arc_maps);
deba@190
   528
      _attributes.swap(other._attributes);
deba@190
   529
deba@190
   530
      _nodes_caption = other._nodes_caption;
deba@190
   531
      _arcs_caption = other._arcs_caption;
deba@190
   532
      _attributes_caption = other._attributes_caption;
deba@190
   533
    }
alpar@209
   534
deba@127
   535
    DigraphWriter& operator=(const DigraphWriter&);
deba@127
   536
deba@127
   537
  public:
deba@127
   538
kpeter@631
   539
    /// \name Writing Rules
alpar@156
   540
    /// @{
alpar@209
   541
kpeter@192
   542
    /// \brief Node map writing rule
alpar@156
   543
    ///
kpeter@192
   544
    /// Add a node map writing rule to the writer.
deba@127
   545
    template <typename Map>
deba@127
   546
    DigraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@127
   547
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   548
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   549
        new _writer_bits::MapStorage<Node, Map>(map);
deba@127
   550
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   551
      return *this;
deba@127
   552
    }
deba@127
   553
alpar@156
   554
    /// \brief Node map writing rule
alpar@156
   555
    ///
alpar@156
   556
    /// Add a node map writing rule with specialized converter to the
alpar@156
   557
    /// writer.
deba@127
   558
    template <typename Map, typename Converter>
alpar@209
   559
    DigraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
   560
                           const Converter& converter = Converter()) {
deba@127
   561
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
   562
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
   563
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@127
   564
      _node_maps.push_back(std::make_pair(caption, storage));
deba@127
   565
      return *this;
deba@127
   566
    }
deba@127
   567
alpar@156
   568
    /// \brief Arc map writing rule
alpar@156
   569
    ///
alpar@156
   570
    /// Add an arc map writing rule to the writer.
deba@127
   571
    template <typename Map>
deba@127
   572
    DigraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@127
   573
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   574
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   575
        new _writer_bits::MapStorage<Arc, Map>(map);
deba@127
   576
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   577
      return *this;
deba@127
   578
    }
deba@127
   579
alpar@156
   580
    /// \brief Arc map writing rule
alpar@156
   581
    ///
alpar@156
   582
    /// Add an arc map writing rule with specialized converter to the
alpar@156
   583
    /// writer.
deba@127
   584
    template <typename Map, typename Converter>
alpar@209
   585
    DigraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
   586
                          const Converter& converter = Converter()) {
deba@127
   587
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
   588
      _writer_bits::MapStorageBase<Arc>* storage =
alpar@209
   589
        new _writer_bits::MapStorage<Arc, Map, Converter>(map, converter);
deba@127
   590
      _arc_maps.push_back(std::make_pair(caption, storage));
deba@127
   591
      return *this;
deba@127
   592
    }
deba@127
   593
alpar@156
   594
    /// \brief Attribute writing rule
alpar@156
   595
    ///
alpar@156
   596
    /// Add an attribute writing rule to the writer.
deba@127
   597
    template <typename Value>
deba@127
   598
    DigraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
   599
      _writer_bits::ValueStorageBase* storage =
alpar@209
   600
        new _writer_bits::ValueStorage<Value>(value);
deba@127
   601
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   602
      return *this;
deba@127
   603
    }
deba@127
   604
alpar@156
   605
    /// \brief Attribute writing rule
alpar@156
   606
    ///
alpar@156
   607
    /// Add an attribute writing rule with specialized converter to the
alpar@156
   608
    /// writer.
deba@127
   609
    template <typename Value, typename Converter>
alpar@209
   610
    DigraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
   611
                             const Converter& converter = Converter()) {
alpar@209
   612
      _writer_bits::ValueStorageBase* storage =
alpar@209
   613
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@127
   614
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   615
      return *this;
deba@127
   616
    }
deba@127
   617
alpar@156
   618
    /// \brief Node writing rule
alpar@156
   619
    ///
alpar@156
   620
    /// Add a node writing rule to the writer.
deba@127
   621
    DigraphWriter& node(const std::string& caption, const Node& node) {
deba@127
   622
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@127
   623
      Converter converter(_node_index);
alpar@209
   624
      _writer_bits::ValueStorageBase* storage =
alpar@209
   625
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@127
   626
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   627
      return *this;
deba@127
   628
    }
deba@127
   629
alpar@156
   630
    /// \brief Arc writing rule
alpar@156
   631
    ///
alpar@156
   632
    /// Add an arc writing rule to writer.
deba@127
   633
    DigraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@127
   634
      typedef _writer_bits::MapLookUpConverter<Arc> Converter;
deba@127
   635
      Converter converter(_arc_index);
alpar@209
   636
      _writer_bits::ValueStorageBase* storage =
alpar@209
   637
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@127
   638
      _attributes.push_back(std::make_pair(caption, storage));
deba@127
   639
      return *this;
deba@127
   640
    }
deba@127
   641
kpeter@631
   642
    /// \name Section Captions
alpar@156
   643
    /// @{
alpar@156
   644
kpeter@192
   645
    /// \brief Add an additional caption to the \c \@nodes section
alpar@156
   646
    ///
kpeter@192
   647
    /// Add an additional caption to the \c \@nodes section.
deba@127
   648
    DigraphWriter& nodes(const std::string& caption) {
deba@127
   649
      _nodes_caption = caption;
deba@127
   650
      return *this;
deba@127
   651
    }
deba@127
   652
kpeter@192
   653
    /// \brief Add an additional caption to the \c \@arcs section
alpar@156
   654
    ///
kpeter@192
   655
    /// Add an additional caption to the \c \@arcs section.
deba@127
   656
    DigraphWriter& arcs(const std::string& caption) {
deba@127
   657
      _arcs_caption = caption;
deba@127
   658
      return *this;
deba@127
   659
    }
deba@127
   660
kpeter@192
   661
    /// \brief Add an additional caption to the \c \@attributes section
alpar@156
   662
    ///
kpeter@192
   663
    /// Add an additional caption to the \c \@attributes section.
deba@127
   664
    DigraphWriter& attributes(const std::string& caption) {
deba@127
   665
      _attributes_caption = caption;
deba@127
   666
      return *this;
deba@127
   667
    }
deba@127
   668
kpeter@631
   669
    /// \name Skipping Section
alpar@156
   670
    /// @{
alpar@156
   671
alpar@156
   672
    /// \brief Skip writing the node set
alpar@156
   673
    ///
kpeter@192
   674
    /// The \c \@nodes section will not be written to the stream.
deba@127
   675
    DigraphWriter& skipNodes() {
deba@127
   676
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
   677
      _skip_nodes = true;
deba@127
   678
      return *this;
deba@127
   679
    }
deba@127
   680
alpar@156
   681
    /// \brief Skip writing arc set
alpar@156
   682
    ///
kpeter@192
   683
    /// The \c \@arcs section will not be written to the stream.
deba@127
   684
    DigraphWriter& skipArcs() {
deba@127
   685
      LEMON_ASSERT(!_skip_arcs, "Multiple usage of skipArcs() member");
deba@185
   686
      _skip_arcs = true;
deba@127
   687
      return *this;
deba@127
   688
    }
deba@127
   689
alpar@156
   690
    /// @}
alpar@156
   691
deba@127
   692
  private:
deba@127
   693
deba@127
   694
    void writeNodes() {
deba@127
   695
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@127
   696
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   697
           it != _node_maps.end(); ++it) {
deba@127
   698
        if (it->first == "label") {
alpar@209
   699
          label = it->second;
alpar@209
   700
          break;
alpar@209
   701
        }
deba@127
   702
      }
deba@127
   703
deba@127
   704
      *_os << "@nodes";
deba@127
   705
      if (!_nodes_caption.empty()) {
alpar@209
   706
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@127
   707
      }
deba@127
   708
      *_os << std::endl;
deba@127
   709
deba@127
   710
      if (label == 0) {
alpar@209
   711
        *_os << "label" << '\t';
deba@127
   712
      }
deba@127
   713
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   714
           it != _node_maps.end(); ++it) {
alpar@209
   715
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   716
      }
deba@127
   717
      *_os << std::endl;
deba@127
   718
deba@127
   719
      std::vector<Node> nodes;
deba@127
   720
      for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   721
        nodes.push_back(n);
deba@127
   722
      }
alpar@209
   723
deba@127
   724
      if (label == 0) {
deba@645
   725
        IdMap<DGR, Node> id_map(_digraph);
deba@645
   726
        _writer_bits::MapLess<IdMap<DGR, Node> > id_less(id_map);
alpar@209
   727
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@127
   728
      } else {
alpar@209
   729
        label->sort(nodes);
deba@127
   730
      }
deba@127
   731
deba@127
   732
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
   733
        Node n = nodes[i];
alpar@209
   734
        if (label == 0) {
alpar@209
   735
          std::ostringstream os;
alpar@209
   736
          os << _digraph.id(n);
alpar@209
   737
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   738
          *_os << '\t';
alpar@209
   739
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   740
        }
alpar@209
   741
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   742
             it != _node_maps.end(); ++it) {
alpar@209
   743
          std::string value = it->second->get(n);
alpar@209
   744
          _writer_bits::writeToken(*_os, value);
alpar@209
   745
          if (it->first == "label") {
alpar@209
   746
            _node_index.insert(std::make_pair(n, value));
alpar@209
   747
          }
alpar@209
   748
          *_os << '\t';
alpar@209
   749
        }
alpar@209
   750
        *_os << std::endl;
deba@127
   751
      }
deba@127
   752
    }
deba@127
   753
deba@185
   754
    void createNodeIndex() {
deba@185
   755
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
   756
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
   757
           it != _node_maps.end(); ++it) {
deba@185
   758
        if (it->first == "label") {
alpar@209
   759
          label = it->second;
alpar@209
   760
          break;
alpar@209
   761
        }
deba@185
   762
      }
deba@185
   763
deba@185
   764
      if (label == 0) {
alpar@209
   765
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   766
          std::ostringstream os;
alpar@209
   767
          os << _digraph.id(n);
alpar@209
   768
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
   769
        }
deba@185
   770
      } else {
alpar@209
   771
        for (NodeIt n(_digraph); n != INVALID; ++n) {
alpar@209
   772
          std::string value = label->get(n);
alpar@209
   773
          _node_index.insert(std::make_pair(n, value));
alpar@209
   774
        }
deba@185
   775
      }
deba@185
   776
    }
deba@185
   777
deba@127
   778
    void writeArcs() {
deba@127
   779
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@127
   780
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   781
           it != _arc_maps.end(); ++it) {
deba@127
   782
        if (it->first == "label") {
alpar@209
   783
          label = it->second;
alpar@209
   784
          break;
alpar@209
   785
        }
deba@127
   786
      }
deba@127
   787
deba@127
   788
      *_os << "@arcs";
deba@127
   789
      if (!_arcs_caption.empty()) {
alpar@209
   790
        _writer_bits::writeToken(*_os << ' ', _arcs_caption);
deba@127
   791
      }
deba@127
   792
      *_os << std::endl;
deba@127
   793
deba@127
   794
      *_os << '\t' << '\t';
deba@127
   795
      if (label == 0) {
alpar@209
   796
        *_os << "label" << '\t';
deba@127
   797
      }
deba@127
   798
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   799
           it != _arc_maps.end(); ++it) {
alpar@209
   800
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@127
   801
      }
deba@127
   802
      *_os << std::endl;
deba@127
   803
deba@127
   804
      std::vector<Arc> arcs;
deba@127
   805
      for (ArcIt n(_digraph); n != INVALID; ++n) {
alpar@209
   806
        arcs.push_back(n);
deba@127
   807
      }
alpar@209
   808
deba@127
   809
      if (label == 0) {
deba@645
   810
        IdMap<DGR, Arc> id_map(_digraph);
deba@645
   811
        _writer_bits::MapLess<IdMap<DGR, Arc> > id_less(id_map);
alpar@209
   812
        std::sort(arcs.begin(), arcs.end(), id_less);
deba@127
   813
      } else {
alpar@209
   814
        label->sort(arcs);
deba@127
   815
      }
deba@127
   816
deba@127
   817
      for (int i = 0; i < static_cast<int>(arcs.size()); ++i) {
alpar@209
   818
        Arc a = arcs[i];
alpar@209
   819
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   820
                                 find(_digraph.source(a))->second);
alpar@209
   821
        *_os << '\t';
alpar@209
   822
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
   823
                                 find(_digraph.target(a))->second);
alpar@209
   824
        *_os << '\t';
alpar@209
   825
        if (label == 0) {
alpar@209
   826
          std::ostringstream os;
alpar@209
   827
          os << _digraph.id(a);
alpar@209
   828
          _writer_bits::writeToken(*_os, os.str());
alpar@209
   829
          *_os << '\t';
alpar@209
   830
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   831
        }
alpar@209
   832
        for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   833
             it != _arc_maps.end(); ++it) {
alpar@209
   834
          std::string value = it->second->get(a);
alpar@209
   835
          _writer_bits::writeToken(*_os, value);
alpar@209
   836
          if (it->first == "label") {
alpar@209
   837
            _arc_index.insert(std::make_pair(a, value));
alpar@209
   838
          }
alpar@209
   839
          *_os << '\t';
alpar@209
   840
        }
alpar@209
   841
        *_os << std::endl;
deba@127
   842
      }
deba@127
   843
    }
deba@127
   844
deba@185
   845
    void createArcIndex() {
deba@185
   846
      _writer_bits::MapStorageBase<Arc>* label = 0;
deba@185
   847
      for (typename ArcMaps::iterator it = _arc_maps.begin();
alpar@209
   848
           it != _arc_maps.end(); ++it) {
deba@185
   849
        if (it->first == "label") {
alpar@209
   850
          label = it->second;
alpar@209
   851
          break;
alpar@209
   852
        }
deba@185
   853
      }
deba@185
   854
deba@185
   855
      if (label == 0) {
alpar@209
   856
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   857
          std::ostringstream os;
alpar@209
   858
          os << _digraph.id(a);
alpar@209
   859
          _arc_index.insert(std::make_pair(a, os.str()));
alpar@209
   860
        }
deba@185
   861
      } else {
alpar@209
   862
        for (ArcIt a(_digraph); a != INVALID; ++a) {
alpar@209
   863
          std::string value = label->get(a);
alpar@209
   864
          _arc_index.insert(std::make_pair(a, value));
alpar@209
   865
        }
deba@185
   866
      }
deba@185
   867
    }
deba@185
   868
deba@127
   869
    void writeAttributes() {
deba@127
   870
      if (_attributes.empty()) return;
deba@127
   871
      *_os << "@attributes";
deba@127
   872
      if (!_attributes_caption.empty()) {
alpar@209
   873
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@127
   874
      }
deba@127
   875
      *_os << std::endl;
deba@127
   876
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
   877
           it != _attributes.end(); ++it) {
alpar@209
   878
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
   879
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
   880
        *_os << std::endl;
deba@127
   881
      }
deba@127
   882
    }
alpar@209
   883
deba@127
   884
  public:
alpar@209
   885
kpeter@631
   886
    /// \name Execution of the Writer
alpar@156
   887
    /// @{
alpar@156
   888
alpar@156
   889
    /// \brief Start the batch processing
alpar@156
   890
    ///
kpeter@192
   891
    /// This function starts the batch processing.
deba@127
   892
    void run() {
deba@127
   893
      if (!_skip_nodes) {
alpar@209
   894
        writeNodes();
deba@185
   895
      } else {
alpar@209
   896
        createNodeIndex();
deba@127
   897
      }
alpar@209
   898
      if (!_skip_arcs) {
alpar@209
   899
        writeArcs();
deba@185
   900
      } else {
alpar@209
   901
        createArcIndex();
deba@127
   902
      }
deba@127
   903
      writeAttributes();
deba@127
   904
    }
deba@127
   905
kpeter@192
   906
    /// \brief Give back the stream of the writer
alpar@156
   907
    ///
kpeter@192
   908
    /// Give back the stream of the writer.
alpar@156
   909
    std::ostream& ostream() {
deba@127
   910
      return *_os;
deba@127
   911
    }
alpar@156
   912
alpar@156
   913
    /// @}
deba@127
   914
  };
deba@127
   915
deba@645
   916
  /// \ingroup lemon_io
deba@645
   917
  ///
kpeter@517
   918
  /// \brief Return a \ref DigraphWriter class
kpeter@517
   919
  ///
deba@645
   920
  /// This function just returns a \ref DigraphWriter class. 
deba@645
   921
  ///
deba@645
   922
  /// With this function a digraph can be write to a file or output
deba@645
   923
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@645
   924
  /// attributes. For example, with the following code a network flow
deba@645
   925
  /// problem can be written to the standard output, i.e. a digraph
deba@645
   926
  /// with a \e capacity map on the arcs and \e source and \e target
deba@645
   927
  /// nodes:
deba@645
   928
  ///
deba@645
   929
  ///\code
deba@645
   930
  ///ListDigraph digraph;
deba@645
   931
  ///ListDigraph::ArcMap<int> cap(digraph);
deba@645
   932
  ///ListDigraph::Node src, trg;
deba@645
   933
  ///  // Setting the capacity map and source and target nodes
deba@645
   934
  ///digraphWriter(digraph, std::cout).
deba@645
   935
  ///  arcMap("capacity", cap).
deba@645
   936
  ///  node("source", src).
deba@645
   937
  ///  node("target", trg).
deba@645
   938
  ///  run();
deba@645
   939
  ///\endcode
deba@645
   940
  ///
deba@645
   941
  /// For a complete documentation, please see the \ref DigraphWriter
deba@645
   942
  /// class documentation.
deba@645
   943
  /// \warning Don't forget to put the \ref DigraphWriter::run() "run()"
deba@645
   944
  /// to the end of the parameter list.
kpeter@517
   945
  /// \relates DigraphWriter
deba@645
   946
  /// \sa digraphWriter(const TDGR& digraph, const std::string& fn)
deba@645
   947
  /// \sa digraphWriter(const TDGR& digraph, const char* fn)
deba@645
   948
  template <typename TDGR>
deba@645
   949
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, std::ostream& os) {
deba@645
   950
    DigraphWriter<TDGR> tmp(digraph, os);
kpeter@517
   951
    return tmp;
kpeter@517
   952
  }
kpeter@517
   953
kpeter@517
   954
  /// \brief Return a \ref DigraphWriter class
kpeter@517
   955
  ///
kpeter@517
   956
  /// This function just returns a \ref DigraphWriter class.
kpeter@517
   957
  /// \relates DigraphWriter
deba@645
   958
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@645
   959
  template <typename TDGR>
deba@645
   960
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, 
deba@645
   961
                                    const std::string& fn) {
deba@645
   962
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@517
   963
    return tmp;
kpeter@517
   964
  }
kpeter@517
   965
kpeter@517
   966
  /// \brief Return a \ref DigraphWriter class
kpeter@517
   967
  ///
kpeter@517
   968
  /// This function just returns a \ref DigraphWriter class.
kpeter@517
   969
  /// \relates DigraphWriter
deba@645
   970
  /// \sa digraphWriter(const TDGR& digraph, std::ostream& os)
deba@645
   971
  template <typename TDGR>
deba@645
   972
  DigraphWriter<TDGR> digraphWriter(const TDGR& digraph, const char* fn) {
deba@645
   973
    DigraphWriter<TDGR> tmp(digraph, fn);
kpeter@517
   974
    return tmp;
kpeter@517
   975
  }
kpeter@517
   976
deba@645
   977
  template <typename GR>
ladanyi@303
   978
  class GraphWriter;
ladanyi@303
   979
deba@645
   980
  template <typename TGR>
deba@645
   981
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os = std::cout);
deba@645
   982
  template <typename TGR>
deba@645
   983
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn);
deba@645
   984
  template <typename TGR>
deba@645
   985
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
deba@165
   986
deba@165
   987
  /// \ingroup lemon_io
alpar@209
   988
  ///
kpeter@192
   989
  /// \brief \ref lgf-format "LGF" writer for directed graphs
deba@165
   990
  ///
deba@165
   991
  /// This utility writes an \ref lgf-format "LGF" file.
kpeter@192
   992
  ///
kpeter@192
   993
  /// It can be used almost the same way as \c DigraphWriter.
kpeter@192
   994
  /// The only difference is that this class can handle edges and
kpeter@192
   995
  /// edge maps as well as arcs and arc maps.
deba@201
   996
  ///
deba@201
   997
  /// The arc maps are written into the file as two columns, the
deba@201
   998
  /// caption of the columns are the name of the map prefixed with \c
deba@201
   999
  /// '+' and \c '-'. The arcs are written into the \c \@attributes
deba@201
  1000
  /// section as a \c '+' or a \c '-' prefix (depends on the direction
deba@201
  1001
  /// of the arc) and the label of corresponding edge.
kpeter@606
  1002
  template <typename GR>
deba@165
  1003
  class GraphWriter {
deba@165
  1004
  public:
deba@165
  1005
kpeter@606
  1006
    typedef GR Graph;
deba@645
  1007
    TEMPLATE_GRAPH_TYPEDEFS(GR);
alpar@209
  1008
deba@165
  1009
  private:
deba@165
  1010
deba@165
  1011
deba@165
  1012
    std::ostream* _os;
deba@165
  1013
    bool local_os;
deba@165
  1014
deba@645
  1015
    const GR& _graph;
deba@165
  1016
deba@165
  1017
    std::string _nodes_caption;
deba@165
  1018
    std::string _edges_caption;
deba@165
  1019
    std::string _attributes_caption;
alpar@209
  1020
deba@165
  1021
    typedef std::map<Node, std::string> NodeIndex;
deba@165
  1022
    NodeIndex _node_index;
deba@165
  1023
    typedef std::map<Edge, std::string> EdgeIndex;
deba@165
  1024
    EdgeIndex _edge_index;
deba@165
  1025
alpar@209
  1026
    typedef std::vector<std::pair<std::string,
alpar@209
  1027
      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
alpar@209
  1028
    NodeMaps _node_maps;
deba@165
  1029
alpar@209
  1030
    typedef std::vector<std::pair<std::string,
deba@165
  1031
      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
deba@165
  1032
    EdgeMaps _edge_maps;
deba@165
  1033
alpar@209
  1034
    typedef std::vector<std::pair<std::string,
deba@165
  1035
      _writer_bits::ValueStorageBase*> > Attributes;
deba@165
  1036
    Attributes _attributes;
deba@165
  1037
deba@165
  1038
    bool _skip_nodes;
deba@165
  1039
    bool _skip_edges;
deba@165
  1040
deba@165
  1041
  public:
deba@165
  1042
deba@165
  1043
    /// \brief Constructor
deba@165
  1044
    ///
deba@165
  1045
    /// Construct a directed graph writer, which writes to the given
deba@165
  1046
    /// output stream.
deba@645
  1047
    GraphWriter(const GR& graph, std::ostream& os = std::cout)
kpeter@293
  1048
      : _os(&os), local_os(false), _graph(graph),
alpar@209
  1049
        _skip_nodes(false), _skip_edges(false) {}
deba@165
  1050
deba@165
  1051
    /// \brief Constructor
deba@165
  1052
    ///
deba@165
  1053
    /// Construct a directed graph writer, which writes to the given
deba@165
  1054
    /// output file.
deba@645
  1055
    GraphWriter(const GR& graph, const std::string& fn)
deba@165
  1056
      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
deba@290
  1057
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1058
      if (!(*_os)) {
deba@295
  1059
        delete _os;
deba@295
  1060
        throw IoError("Cannot write file", fn);
deba@295
  1061
      }
deba@290
  1062
    }
deba@165
  1063
deba@165
  1064
    /// \brief Constructor
deba@165
  1065
    ///
deba@165
  1066
    /// Construct a directed graph writer, which writes to the given
deba@165
  1067
    /// output file.
deba@645
  1068
    GraphWriter(const GR& graph, const char* fn)
deba@165
  1069
      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
deba@290
  1070
        _skip_nodes(false), _skip_edges(false) {
deba@295
  1071
      if (!(*_os)) {
deba@295
  1072
        delete _os;
deba@295
  1073
        throw IoError("Cannot write file", fn);
deba@295
  1074
      }
deba@290
  1075
    }
deba@165
  1076
deba@165
  1077
    /// \brief Destructor
deba@165
  1078
    ~GraphWriter() {
alpar@209
  1079
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1080
           it != _node_maps.end(); ++it) {
alpar@209
  1081
        delete it->second;
deba@165
  1082
      }
deba@165
  1083
alpar@209
  1084
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1085
           it != _edge_maps.end(); ++it) {
alpar@209
  1086
        delete it->second;
deba@165
  1087
      }
deba@165
  1088
alpar@209
  1089
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1090
           it != _attributes.end(); ++it) {
alpar@209
  1091
        delete it->second;
deba@165
  1092
      }
deba@165
  1093
deba@165
  1094
      if (local_os) {
alpar@209
  1095
        delete _os;
deba@165
  1096
      }
deba@165
  1097
    }
alpar@209
  1098
deba@190
  1099
  private:
deba@165
  1100
deba@645
  1101
    template <typename TGR>
deba@645
  1102
    friend GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os);
deba@645
  1103
    template <typename TGR>
deba@645
  1104
    friend GraphWriter<TGR> graphWriter(const TGR& graph, 
deba@645
  1105
                                        const std::string& fn);
deba@645
  1106
    template <typename TGR>
deba@645
  1107
    friend GraphWriter<TGR> graphWriter(const TGR& graph, const char *fn);
kpeter@517
  1108
    
alpar@209
  1109
    GraphWriter(GraphWriter& other)
deba@190
  1110
      : _os(other._os), local_os(other.local_os), _graph(other._graph),
alpar@209
  1111
        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
deba@190
  1112
deba@190
  1113
      other._os = 0;
deba@190
  1114
      other.local_os = false;
deba@190
  1115
deba@190
  1116
      _node_index.swap(other._node_index);
deba@190
  1117
      _edge_index.swap(other._edge_index);
deba@190
  1118
deba@190
  1119
      _node_maps.swap(other._node_maps);
deba@190
  1120
      _edge_maps.swap(other._edge_maps);
deba@190
  1121
      _attributes.swap(other._attributes);
deba@190
  1122
deba@190
  1123
      _nodes_caption = other._nodes_caption;
deba@190
  1124
      _edges_caption = other._edges_caption;
deba@190
  1125
      _attributes_caption = other._attributes_caption;
deba@190
  1126
    }
deba@190
  1127
deba@165
  1128
    GraphWriter& operator=(const GraphWriter&);
deba@165
  1129
deba@165
  1130
  public:
deba@165
  1131
kpeter@631
  1132
    /// \name Writing Rules
deba@165
  1133
    /// @{
alpar@209
  1134
kpeter@192
  1135
    /// \brief Node map writing rule
deba@165
  1136
    ///
kpeter@192
  1137
    /// Add a node map writing rule to the writer.
deba@165
  1138
    template <typename Map>
deba@165
  1139
    GraphWriter& nodeMap(const std::string& caption, const Map& map) {
deba@165
  1140
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1141
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1142
        new _writer_bits::MapStorage<Node, Map>(map);
deba@165
  1143
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1144
      return *this;
deba@165
  1145
    }
deba@165
  1146
deba@165
  1147
    /// \brief Node map writing rule
deba@165
  1148
    ///
deba@165
  1149
    /// Add a node map writing rule with specialized converter to the
deba@165
  1150
    /// writer.
deba@165
  1151
    template <typename Map, typename Converter>
alpar@209
  1152
    GraphWriter& nodeMap(const std::string& caption, const Map& map,
alpar@209
  1153
                           const Converter& converter = Converter()) {
deba@165
  1154
      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
alpar@209
  1155
      _writer_bits::MapStorageBase<Node>* storage =
alpar@209
  1156
        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
deba@165
  1157
      _node_maps.push_back(std::make_pair(caption, storage));
deba@165
  1158
      return *this;
deba@165
  1159
    }
deba@165
  1160
deba@165
  1161
    /// \brief Edge map writing rule
deba@165
  1162
    ///
deba@165
  1163
    /// Add an edge map writing rule to the writer.
deba@165
  1164
    template <typename Map>
deba@165
  1165
    GraphWriter& edgeMap(const std::string& caption, const Map& map) {
deba@165
  1166
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1167
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1168
        new _writer_bits::MapStorage<Edge, Map>(map);
deba@165
  1169
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1170
      return *this;
deba@165
  1171
    }
deba@165
  1172
deba@165
  1173
    /// \brief Edge map writing rule
deba@165
  1174
    ///
deba@165
  1175
    /// Add an edge map writing rule with specialized converter to the
deba@165
  1176
    /// writer.
deba@165
  1177
    template <typename Map, typename Converter>
alpar@209
  1178
    GraphWriter& edgeMap(const std::string& caption, const Map& map,
alpar@209
  1179
                          const Converter& converter = Converter()) {
deba@165
  1180
      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
alpar@209
  1181
      _writer_bits::MapStorageBase<Edge>* storage =
alpar@209
  1182
        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
deba@165
  1183
      _edge_maps.push_back(std::make_pair(caption, storage));
deba@165
  1184
      return *this;
deba@165
  1185
    }
deba@165
  1186
deba@165
  1187
    /// \brief Arc map writing rule
deba@165
  1188
    ///
deba@165
  1189
    /// Add an arc map writing rule to the writer.
deba@165
  1190
    template <typename Map>
deba@165
  1191
    GraphWriter& arcMap(const std::string& caption, const Map& map) {
deba@165
  1192
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1193
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@645
  1194
        new _writer_bits::GraphArcMapStorage<GR, true, Map>(_graph, map);
deba@165
  1195
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1196
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@645
  1197
        new _writer_bits::GraphArcMapStorage<GR, false, Map>(_graph, map);
deba@165
  1198
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1199
      return *this;
deba@165
  1200
    }
deba@165
  1201
deba@165
  1202
    /// \brief Arc map writing rule
deba@165
  1203
    ///
deba@165
  1204
    /// Add an arc map writing rule with specialized converter to the
deba@165
  1205
    /// writer.
deba@165
  1206
    template <typename Map, typename Converter>
alpar@209
  1207
    GraphWriter& arcMap(const std::string& caption, const Map& map,
alpar@209
  1208
                          const Converter& converter = Converter()) {
deba@165
  1209
      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
alpar@209
  1210
      _writer_bits::MapStorageBase<Edge>* forward_storage =
deba@645
  1211
        new _writer_bits::GraphArcMapStorage<GR, true, Map, Converter>
alpar@209
  1212
        (_graph, map, converter);
deba@165
  1213
      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
alpar@209
  1214
      _writer_bits::MapStorageBase<Edge>* backward_storage =
deba@645
  1215
        new _writer_bits::GraphArcMapStorage<GR, false, Map, Converter>
alpar@209
  1216
        (_graph, map, converter);
deba@165
  1217
      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
deba@165
  1218
      return *this;
deba@165
  1219
    }
deba@165
  1220
deba@165
  1221
    /// \brief Attribute writing rule
deba@165
  1222
    ///
deba@165
  1223
    /// Add an attribute writing rule to the writer.
deba@165
  1224
    template <typename Value>
deba@165
  1225
    GraphWriter& attribute(const std::string& caption, const Value& value) {
alpar@209
  1226
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1227
        new _writer_bits::ValueStorage<Value>(value);
deba@165
  1228
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1229
      return *this;
deba@165
  1230
    }
deba@165
  1231
deba@165
  1232
    /// \brief Attribute writing rule
deba@165
  1233
    ///
deba@165
  1234
    /// Add an attribute writing rule with specialized converter to the
deba@165
  1235
    /// writer.
deba@165
  1236
    template <typename Value, typename Converter>
alpar@209
  1237
    GraphWriter& attribute(const std::string& caption, const Value& value,
alpar@209
  1238
                             const Converter& converter = Converter()) {
alpar@209
  1239
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1240
        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
deba@165
  1241
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1242
      return *this;
deba@165
  1243
    }
deba@165
  1244
deba@165
  1245
    /// \brief Node writing rule
deba@165
  1246
    ///
deba@165
  1247
    /// Add a node writing rule to the writer.
deba@165
  1248
    GraphWriter& node(const std::string& caption, const Node& node) {
deba@165
  1249
      typedef _writer_bits::MapLookUpConverter<Node> Converter;
deba@165
  1250
      Converter converter(_node_index);
alpar@209
  1251
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1252
        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
deba@165
  1253
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1254
      return *this;
deba@165
  1255
    }
deba@165
  1256
deba@165
  1257
    /// \brief Edge writing rule
deba@165
  1258
    ///
deba@165
  1259
    /// Add an edge writing rule to writer.
deba@165
  1260
    GraphWriter& edge(const std::string& caption, const Edge& edge) {
deba@165
  1261
      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
deba@165
  1262
      Converter converter(_edge_index);
alpar@209
  1263
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1264
        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
deba@165
  1265
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1266
      return *this;
deba@165
  1267
    }
deba@165
  1268
deba@165
  1269
    /// \brief Arc writing rule
deba@165
  1270
    ///
deba@165
  1271
    /// Add an arc writing rule to writer.
deba@165
  1272
    GraphWriter& arc(const std::string& caption, const Arc& arc) {
deba@645
  1273
      typedef _writer_bits::GraphArcLookUpConverter<GR> Converter;
deba@165
  1274
      Converter converter(_graph, _edge_index);
alpar@209
  1275
      _writer_bits::ValueStorageBase* storage =
alpar@209
  1276
        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
deba@165
  1277
      _attributes.push_back(std::make_pair(caption, storage));
deba@165
  1278
      return *this;
deba@165
  1279
    }
deba@165
  1280
kpeter@631
  1281
    /// \name Section Captions
deba@165
  1282
    /// @{
deba@165
  1283
kpeter@192
  1284
    /// \brief Add an additional caption to the \c \@nodes section
deba@165
  1285
    ///
kpeter@192
  1286
    /// Add an additional caption to the \c \@nodes section.
deba@165
  1287
    GraphWriter& nodes(const std::string& caption) {
deba@165
  1288
      _nodes_caption = caption;
deba@165
  1289
      return *this;
deba@165
  1290
    }
deba@165
  1291
kpeter@192
  1292
    /// \brief Add an additional caption to the \c \@arcs section
deba@165
  1293
    ///
kpeter@192
  1294
    /// Add an additional caption to the \c \@arcs section.
deba@165
  1295
    GraphWriter& edges(const std::string& caption) {
deba@165
  1296
      _edges_caption = caption;
deba@165
  1297
      return *this;
deba@165
  1298
    }
deba@165
  1299
kpeter@192
  1300
    /// \brief Add an additional caption to the \c \@attributes section
deba@165
  1301
    ///
kpeter@192
  1302
    /// Add an additional caption to the \c \@attributes section.
deba@165
  1303
    GraphWriter& attributes(const std::string& caption) {
deba@165
  1304
      _attributes_caption = caption;
deba@165
  1305
      return *this;
deba@165
  1306
    }
deba@165
  1307
kpeter@631
  1308
    /// \name Skipping Section
deba@165
  1309
    /// @{
deba@165
  1310
deba@165
  1311
    /// \brief Skip writing the node set
deba@165
  1312
    ///
kpeter@192
  1313
    /// The \c \@nodes section will not be written to the stream.
deba@165
  1314
    GraphWriter& skipNodes() {
deba@165
  1315
      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
deba@185
  1316
      _skip_nodes = true;
deba@165
  1317
      return *this;
deba@165
  1318
    }
deba@165
  1319
deba@165
  1320
    /// \brief Skip writing edge set
deba@165
  1321
    ///
kpeter@192
  1322
    /// The \c \@edges section will not be written to the stream.
deba@165
  1323
    GraphWriter& skipEdges() {
deba@165
  1324
      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
deba@185
  1325
      _skip_edges = true;
deba@165
  1326
      return *this;
deba@165
  1327
    }
deba@165
  1328
deba@165
  1329
    /// @}
deba@165
  1330
deba@165
  1331
  private:
deba@165
  1332
deba@165
  1333
    void writeNodes() {
deba@165
  1334
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@165
  1335
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1336
           it != _node_maps.end(); ++it) {
deba@165
  1337
        if (it->first == "label") {
alpar@209
  1338
          label = it->second;
alpar@209
  1339
          break;
alpar@209
  1340
        }
deba@165
  1341
      }
deba@165
  1342
deba@165
  1343
      *_os << "@nodes";
deba@165
  1344
      if (!_nodes_caption.empty()) {
alpar@209
  1345
        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
deba@165
  1346
      }
deba@165
  1347
      *_os << std::endl;
deba@165
  1348
deba@165
  1349
      if (label == 0) {
alpar@209
  1350
        *_os << "label" << '\t';
deba@165
  1351
      }
deba@165
  1352
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1353
           it != _node_maps.end(); ++it) {
alpar@209
  1354
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1355
      }
deba@165
  1356
      *_os << std::endl;
deba@165
  1357
deba@165
  1358
      std::vector<Node> nodes;
deba@165
  1359
      for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1360
        nodes.push_back(n);
deba@165
  1361
      }
alpar@209
  1362
deba@165
  1363
      if (label == 0) {
deba@645
  1364
        IdMap<GR, Node> id_map(_graph);
deba@645
  1365
        _writer_bits::MapLess<IdMap<GR, Node> > id_less(id_map);
alpar@209
  1366
        std::sort(nodes.begin(), nodes.end(), id_less);
deba@165
  1367
      } else {
alpar@209
  1368
        label->sort(nodes);
deba@165
  1369
      }
deba@165
  1370
deba@165
  1371
      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
alpar@209
  1372
        Node n = nodes[i];
alpar@209
  1373
        if (label == 0) {
alpar@209
  1374
          std::ostringstream os;
alpar@209
  1375
          os << _graph.id(n);
alpar@209
  1376
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1377
          *_os << '\t';
alpar@209
  1378
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1379
        }
alpar@209
  1380
        for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1381
             it != _node_maps.end(); ++it) {
alpar@209
  1382
          std::string value = it->second->get(n);
alpar@209
  1383
          _writer_bits::writeToken(*_os, value);
alpar@209
  1384
          if (it->first == "label") {
alpar@209
  1385
            _node_index.insert(std::make_pair(n, value));
alpar@209
  1386
          }
alpar@209
  1387
          *_os << '\t';
alpar@209
  1388
        }
alpar@209
  1389
        *_os << std::endl;
deba@165
  1390
      }
deba@165
  1391
    }
deba@165
  1392
deba@185
  1393
    void createNodeIndex() {
deba@185
  1394
      _writer_bits::MapStorageBase<Node>* label = 0;
deba@185
  1395
      for (typename NodeMaps::iterator it = _node_maps.begin();
alpar@209
  1396
           it != _node_maps.end(); ++it) {
deba@185
  1397
        if (it->first == "label") {
alpar@209
  1398
          label = it->second;
alpar@209
  1399
          break;
alpar@209
  1400
        }
deba@185
  1401
      }
deba@185
  1402
deba@185
  1403
      if (label == 0) {
alpar@209
  1404
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1405
          std::ostringstream os;
alpar@209
  1406
          os << _graph.id(n);
alpar@209
  1407
          _node_index.insert(std::make_pair(n, os.str()));
alpar@209
  1408
        }
deba@185
  1409
      } else {
alpar@209
  1410
        for (NodeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1411
          std::string value = label->get(n);
alpar@209
  1412
          _node_index.insert(std::make_pair(n, value));
alpar@209
  1413
        }
deba@185
  1414
      }
deba@185
  1415
    }
deba@185
  1416
deba@165
  1417
    void writeEdges() {
deba@165
  1418
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@165
  1419
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1420
           it != _edge_maps.end(); ++it) {
deba@165
  1421
        if (it->first == "label") {
alpar@209
  1422
          label = it->second;
alpar@209
  1423
          break;
alpar@209
  1424
        }
deba@165
  1425
      }
deba@165
  1426
deba@165
  1427
      *_os << "@edges";
deba@165
  1428
      if (!_edges_caption.empty()) {
alpar@209
  1429
        _writer_bits::writeToken(*_os << ' ', _edges_caption);
deba@165
  1430
      }
deba@165
  1431
      *_os << std::endl;
deba@165
  1432
deba@165
  1433
      *_os << '\t' << '\t';
deba@165
  1434
      if (label == 0) {
alpar@209
  1435
        *_os << "label" << '\t';
deba@165
  1436
      }
deba@165
  1437
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1438
           it != _edge_maps.end(); ++it) {
alpar@209
  1439
        _writer_bits::writeToken(*_os, it->first) << '\t';
deba@165
  1440
      }
deba@165
  1441
      *_os << std::endl;
deba@165
  1442
deba@165
  1443
      std::vector<Edge> edges;
deba@165
  1444
      for (EdgeIt n(_graph); n != INVALID; ++n) {
alpar@209
  1445
        edges.push_back(n);
deba@165
  1446
      }
alpar@209
  1447
deba@165
  1448
      if (label == 0) {
deba@645
  1449
        IdMap<GR, Edge> id_map(_graph);
deba@645
  1450
        _writer_bits::MapLess<IdMap<GR, Edge> > id_less(id_map);
alpar@209
  1451
        std::sort(edges.begin(), edges.end(), id_less);
deba@165
  1452
      } else {
alpar@209
  1453
        label->sort(edges);
deba@165
  1454
      }
deba@165
  1455
deba@165
  1456
      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
alpar@209
  1457
        Edge e = edges[i];
alpar@209
  1458
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1459
                                 find(_graph.u(e))->second);
alpar@209
  1460
        *_os << '\t';
alpar@209
  1461
        _writer_bits::writeToken(*_os, _node_index.
alpar@209
  1462
                                 find(_graph.v(e))->second);
alpar@209
  1463
        *_os << '\t';
alpar@209
  1464
        if (label == 0) {
alpar@209
  1465
          std::ostringstream os;
alpar@209
  1466
          os << _graph.id(e);
alpar@209
  1467
          _writer_bits::writeToken(*_os, os.str());
alpar@209
  1468
          *_os << '\t';
alpar@209
  1469
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1470
        }
alpar@209
  1471
        for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1472
             it != _edge_maps.end(); ++it) {
alpar@209
  1473
          std::string value = it->second->get(e);
alpar@209
  1474
          _writer_bits::writeToken(*_os, value);
alpar@209
  1475
          if (it->first == "label") {
alpar@209
  1476
            _edge_index.insert(std::make_pair(e, value));
alpar@209
  1477
          }
alpar@209
  1478
          *_os << '\t';
alpar@209
  1479
        }
alpar@209
  1480
        *_os << std::endl;
deba@165
  1481
      }
deba@165
  1482
    }
deba@165
  1483
deba@185
  1484
    void createEdgeIndex() {
deba@185
  1485
      _writer_bits::MapStorageBase<Edge>* label = 0;
deba@185
  1486
      for (typename EdgeMaps::iterator it = _edge_maps.begin();
alpar@209
  1487
           it != _edge_maps.end(); ++it) {
deba@185
  1488
        if (it->first == "label") {
alpar@209
  1489
          label = it->second;
alpar@209
  1490
          break;
alpar@209
  1491
        }
deba@185
  1492
      }
deba@185
  1493
deba@185
  1494
      if (label == 0) {
alpar@209
  1495
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1496
          std::ostringstream os;
alpar@209
  1497
          os << _graph.id(e);
alpar@209
  1498
          _edge_index.insert(std::make_pair(e, os.str()));
alpar@209
  1499
        }
deba@185
  1500
      } else {
alpar@209
  1501
        for (EdgeIt e(_graph); e != INVALID; ++e) {
alpar@209
  1502
          std::string value = label->get(e);
alpar@209
  1503
          _edge_index.insert(std::make_pair(e, value));
alpar@209
  1504
        }
deba@185
  1505
      }
deba@185
  1506
    }
deba@185
  1507
deba@165
  1508
    void writeAttributes() {
deba@165
  1509
      if (_attributes.empty()) return;
deba@165
  1510
      *_os << "@attributes";
deba@165
  1511
      if (!_attributes_caption.empty()) {
alpar@209
  1512
        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
deba@165
  1513
      }
deba@165
  1514
      *_os << std::endl;
deba@165
  1515
      for (typename Attributes::iterator it = _attributes.begin();
alpar@209
  1516
           it != _attributes.end(); ++it) {
alpar@209
  1517
        _writer_bits::writeToken(*_os, it->first) << ' ';
alpar@209
  1518
        _writer_bits::writeToken(*_os, it->second->get());
alpar@209
  1519
        *_os << std::endl;
deba@165
  1520
      }
deba@165
  1521
    }
alpar@209
  1522
deba@165
  1523
  public:
alpar@209
  1524
kpeter@631
  1525
    /// \name Execution of the Writer
deba@165
  1526
    /// @{
deba@165
  1527
deba@165
  1528
    /// \brief Start the batch processing
deba@165
  1529
    ///
kpeter@192
  1530
    /// This function starts the batch processing.
deba@165
  1531
    void run() {
deba@165
  1532
      if (!_skip_nodes) {
alpar@209
  1533
        writeNodes();
deba@185
  1534
      } else {
alpar@209
  1535
        createNodeIndex();
deba@165
  1536
      }
alpar@209
  1537
      if (!_skip_edges) {
alpar@209
  1538
        writeEdges();
deba@185
  1539
      } else {
alpar@209
  1540
        createEdgeIndex();
deba@165
  1541
      }
deba@165
  1542
      writeAttributes();
deba@165
  1543
    }
deba@165
  1544
kpeter@192
  1545
    /// \brief Give back the stream of the writer
deba@165
  1546
    ///
kpeter@192
  1547
    /// Give back the stream of the writer
deba@165
  1548
    std::ostream& ostream() {
deba@165
  1549
      return *_os;
deba@165
  1550
    }
deba@165
  1551
deba@165
  1552
    /// @}
deba@165
  1553
  };
deba@165
  1554
deba@645
  1555
  /// \ingroup lemon_io
deba@645
  1556
  ///
kpeter@517
  1557
  /// \brief Return a \ref GraphWriter class
kpeter@517
  1558
  ///
deba@645
  1559
  /// This function just returns a \ref GraphWriter class. 
deba@645
  1560
  ///
deba@645
  1561
  /// With this function a graph can be write to a file or output
deba@645
  1562
  /// stream in \ref lgf-format "LGF" format with several maps and
deba@645
  1563
  /// attributes. For example, with the following code a weighted
deba@645
  1564
  /// matching problem can be written to the standard output, i.e. a
deba@645
  1565
  /// graph with a \e weight map on the edges:
deba@645
  1566
  ///
deba@645
  1567
  ///\code
deba@645
  1568
  ///ListGraph graph;
deba@645
  1569
  ///ListGraph::EdgeMap<int> weight(graph);
deba@645
  1570
  ///  // Setting the weight map
deba@645
  1571
  ///graphWriter(graph, std::cout).
deba@645
  1572
  ///  edgeMap("weight", weight).
deba@645
  1573
  ///  run();
deba@645
  1574
  ///\endcode
deba@645
  1575
  ///
deba@645
  1576
  /// For a complete documentation, please see the \ref GraphWriter
deba@645
  1577
  /// class documentation.
deba@645
  1578
  /// \warning Don't forget to put the \ref GraphWriter::run() "run()"
deba@645
  1579
  /// to the end of the parameter list.
kpeter@517
  1580
  /// \relates GraphWriter
deba@645
  1581
  /// \sa graphWriter(const TGR& graph, const std::string& fn)
deba@645
  1582
  /// \sa graphWriter(const TGR& graph, const char* fn)
deba@645
  1583
  template <typename TGR>
deba@645
  1584
  GraphWriter<TGR> graphWriter(const TGR& graph, std::ostream& os) {
deba@645
  1585
    GraphWriter<TGR> tmp(graph, os);
kpeter@517
  1586
    return tmp;
kpeter@517
  1587
  }
kpeter@517
  1588
kpeter@517
  1589
  /// \brief Return a \ref GraphWriter class
kpeter@517
  1590
  ///
kpeter@517
  1591
  /// This function just returns a \ref GraphWriter class.
kpeter@517
  1592
  /// \relates GraphWriter
deba@645
  1593
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@645
  1594
  template <typename TGR>
deba@645
  1595
  GraphWriter<TGR> graphWriter(const TGR& graph, const std::string& fn) {
deba@645
  1596
    GraphWriter<TGR> tmp(graph, fn);
kpeter@517
  1597
    return tmp;
kpeter@517
  1598
  }
kpeter@517
  1599
kpeter@517
  1600
  /// \brief Return a \ref GraphWriter class
kpeter@517
  1601
  ///
kpeter@517
  1602
  /// This function just returns a \ref GraphWriter class.
kpeter@517
  1603
  /// \relates GraphWriter
deba@645
  1604
  /// \sa graphWriter(const TGR& graph, std::ostream& os)
deba@645
  1605
  template <typename TGR>
deba@645
  1606
  GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
deba@645
  1607
    GraphWriter<TGR> tmp(graph, fn);
kpeter@517
  1608
    return tmp;
kpeter@517
  1609
  }
kpeter@517
  1610
deba@248
  1611
  class SectionWriter;
deba@248
  1612
deba@248
  1613
  SectionWriter sectionWriter(std::istream& is);
deba@248
  1614
  SectionWriter sectionWriter(const std::string& fn);
deba@248
  1615
  SectionWriter sectionWriter(const char* fn);
deba@248
  1616
deba@248
  1617
  /// \ingroup lemon_io
deba@248
  1618
  ///
deba@248
  1619
  /// \brief Section writer class
deba@248
  1620
  ///
deba@248
  1621
  /// In the \ref lgf-format "LGF" file extra sections can be placed,
deba@248
  1622
  /// which contain any data in arbitrary format. Such sections can be
deba@248
  1623
  /// written with this class. A writing rule can be added to the
deba@248
  1624
  /// class with two different functions. With the \c sectionLines()
deba@248
  1625
  /// function a generator can write the section line-by-line, while
deba@248
  1626
  /// with the \c sectionStream() member the section can be written to
deba@248
  1627
  /// an output stream.
deba@248
  1628
  class SectionWriter {
deba@248
  1629
  private:
deba@248
  1630
deba@248
  1631
    std::ostream* _os;
deba@248
  1632
    bool local_os;
deba@248
  1633
deba@248
  1634
    typedef std::vector<std::pair<std::string, _writer_bits::Section*> >
deba@248
  1635
    Sections;
deba@248
  1636
deba@248
  1637
    Sections _sections;
deba@248
  1638
deba@248
  1639
  public:
deba@248
  1640
deba@248
  1641
    /// \brief Constructor
deba@248
  1642
    ///
deba@248
  1643
    /// Construct a section writer, which writes to the given output
deba@248
  1644
    /// stream.
deba@248
  1645
    SectionWriter(std::ostream& os)
deba@248
  1646
      : _os(&os), local_os(false) {}
deba@248
  1647
deba@248
  1648
    /// \brief Constructor
deba@248
  1649
    ///
deba@248
  1650
    /// Construct a section writer, which writes into the given file.
deba@248
  1651
    SectionWriter(const std::string& fn)
deba@290
  1652
      : _os(new std::ofstream(fn.c_str())), local_os(true) {
deba@295
  1653
      if (!(*_os)) {
deba@295
  1654
        delete _os;
deba@295
  1655
        throw IoError("Cannot write file", fn);
deba@295
  1656
      }
deba@290
  1657
    }
deba@248
  1658
deba@248
  1659
    /// \brief Constructor
deba@248
  1660
    ///
deba@248
  1661
    /// Construct a section writer, which writes into the given file.
deba@248
  1662
    SectionWriter(const char* fn)
deba@290
  1663
      : _os(new std::ofstream(fn)), local_os(true) {
deba@295
  1664
      if (!(*_os)) {
deba@295
  1665
        delete _os;
deba@295
  1666
        throw IoError("Cannot write file", fn);
deba@295
  1667
      }
deba@290
  1668
    }
deba@248
  1669
deba@248
  1670
    /// \brief Destructor
deba@248
  1671
    ~SectionWriter() {
deba@248
  1672
      for (Sections::iterator it = _sections.begin();
deba@248
  1673
           it != _sections.end(); ++it) {
deba@248
  1674
        delete it->second;
deba@248
  1675
      }
deba@248
  1676
deba@248
  1677
      if (local_os) {
deba@248
  1678
        delete _os;
deba@248
  1679
      }
deba@248
  1680
deba@248
  1681
    }
deba@248
  1682
deba@248
  1683
  private:
deba@248
  1684
deba@248
  1685
    friend SectionWriter sectionWriter(std::ostream& os);
deba@248
  1686
    friend SectionWriter sectionWriter(const std::string& fn);
deba@248
  1687
    friend SectionWriter sectionWriter(const char* fn);
deba@248
  1688
deba@248
  1689
    SectionWriter(SectionWriter& other)
deba@248
  1690
      : _os(other._os), local_os(other.local_os) {
deba@248
  1691
deba@248
  1692
      other._os = 0;
deba@248
  1693
      other.local_os = false;
deba@248
  1694
deba@248
  1695
      _sections.swap(other._sections);
deba@248
  1696
    }
deba@248
  1697
deba@248
  1698
    SectionWriter& operator=(const SectionWriter&);
deba@248
  1699
deba@248
  1700
  public:
deba@248
  1701
kpeter@631
  1702
    /// \name Section Writers
deba@248
  1703
    /// @{
deba@248
  1704
deba@248
  1705
    /// \brief Add a section writer with line oriented writing
deba@248
  1706
    ///
deba@248
  1707
    /// The first parameter is the type descriptor of the section, the
deba@248
  1708
    /// second is a generator with std::string values. At the writing
deba@248
  1709
    /// process, the returned \c std::string will be written into the
deba@248
  1710
    /// output file until it is an empty string.
deba@248
  1711
    ///
deba@248
  1712
    /// For example, an integer vector is written into a section.
deba@248
  1713
    ///\code
deba@248
  1714
    ///  @numbers
deba@248
  1715
    ///  12 45 23 78
deba@248
  1716
    ///  4 28 38 28
deba@248
  1717
    ///  23 6 16
deba@248
  1718
    ///\endcode
deba@248
  1719
    ///
deba@248
  1720
    /// The generator is implemented as a struct.
deba@248
  1721
    ///\code
deba@248
  1722
    ///  struct NumberSection {
deba@248
  1723
    ///    std::vector<int>::const_iterator _it, _end;
deba@248
  1724
    ///    NumberSection(const std::vector<int>& data)
deba@248
  1725
    ///      : _it(data.begin()), _end(data.end()) {}
deba@248
  1726
    ///    std::string operator()() {
deba@248
  1727
    ///      int rem_in_line = 4;
deba@248
  1728
    ///      std::ostringstream ls;
deba@248
  1729
    ///      while (rem_in_line > 0 && _it != _end) {
deba@248
  1730
    ///        ls << *(_it++) << ' ';
deba@248
  1731
    ///        --rem_in_line;
deba@248
  1732
    ///      }
deba@248
  1733
    ///      return ls.str();
deba@248
  1734
    ///    }
deba@248
  1735
    ///  };
deba@248
  1736
    ///
deba@248
  1737
    ///  // ...
deba@248
  1738
    ///
deba@248
  1739
    ///  writer.sectionLines("numbers", NumberSection(vec));
deba@248
  1740
    ///\endcode
deba@248
  1741
    template <typename Functor>
deba@248
  1742
    SectionWriter& sectionLines(const std::string& type, Functor functor) {
deba@248
  1743
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  1744
      _sections.push_back(std::make_pair(type,
deba@248
  1745
        new _writer_bits::LineSection<Functor>(functor)));
deba@248
  1746
      return *this;
deba@248
  1747
    }
deba@248
  1748
deba@248
  1749
deba@248
  1750
    /// \brief Add a section writer with stream oriented writing
deba@248
  1751
    ///
deba@248
  1752
    /// The first parameter is the type of the section, the second is
deba@248
  1753
    /// a functor, which takes a \c std::ostream& parameter. The
deba@248
  1754
    /// functor writes the section to the output stream.
deba@248
  1755
    /// \warning The last line must be closed with end-line character.
deba@248
  1756
    template <typename Functor>
deba@248
  1757
    SectionWriter& sectionStream(const std::string& type, Functor functor) {
deba@248
  1758
      LEMON_ASSERT(!type.empty(), "Type is empty.");
deba@248
  1759
      _sections.push_back(std::make_pair(type,
deba@248
  1760
         new _writer_bits::StreamSection<Functor>(functor)));
deba@248
  1761
      return *this;
deba@248
  1762
    }
deba@248
  1763
deba@248
  1764
    /// @}
deba@248
  1765
deba@248
  1766
  public:
deba@248
  1767
deba@248
  1768
kpeter@631
  1769
    /// \name Execution of the Writer
deba@248
  1770
    /// @{
deba@248
  1771
deba@248
  1772
    /// \brief Start the batch processing
deba@248
  1773
    ///
deba@248
  1774
    /// This function starts the batch processing.
deba@248
  1775
    void run() {
deba@248
  1776
deba@248
  1777
      LEMON_ASSERT(_os != 0, "This writer is assigned to an other writer");
deba@248
  1778
deba@248
  1779
      for (Sections::iterator it = _sections.begin();
deba@248
  1780
           it != _sections.end(); ++it) {
deba@248
  1781
        (*_os) << '@' << it->first << std::endl;
deba@248
  1782
        it->second->process(*_os);
deba@248
  1783
      }
deba@248
  1784
    }
deba@248
  1785
deba@248
  1786
    /// \brief Give back the stream of the writer
deba@248
  1787
    ///
deba@248
  1788
    /// Returns the stream of the writer
deba@248
  1789
    std::ostream& ostream() {
deba@248
  1790
      return *_os;
deba@248
  1791
    }
deba@248
  1792
deba@248
  1793
    /// @}
deba@248
  1794
deba@248
  1795
  };
deba@248
  1796
deba@645
  1797
  /// \ingroup lemon_io
deba@645
  1798
  ///
deba@248
  1799
  /// \brief Return a \ref SectionWriter class
deba@248
  1800
  ///
deba@248
  1801
  /// This function just returns a \ref SectionWriter class.
deba@645
  1802
  ///
deba@645
  1803
  /// Please see SectionWriter documentation about the custom section
deba@645
  1804
  /// output.
deba@645
  1805
  ///
deba@248
  1806
  /// \relates SectionWriter
deba@645
  1807
  /// \sa sectionWriter(const std::string& fn)
deba@645
  1808
  /// \sa sectionWriter(const char *fn)
deba@248
  1809
  inline SectionWriter sectionWriter(std::ostream& os) {
deba@248
  1810
    SectionWriter tmp(os);
deba@248
  1811
    return tmp;
deba@248
  1812
  }
deba@248
  1813
deba@248
  1814
  /// \brief Return a \ref SectionWriter class
deba@248
  1815
  ///
deba@248
  1816
  /// This function just returns a \ref SectionWriter class.
deba@248
  1817
  /// \relates SectionWriter
deba@645
  1818
  /// \sa sectionWriter(std::ostream& os)
deba@248
  1819
  inline SectionWriter sectionWriter(const std::string& fn) {
deba@248
  1820
    SectionWriter tmp(fn);
deba@248
  1821
    return tmp;
deba@248
  1822
  }
deba@248
  1823
deba@248
  1824
  /// \brief Return a \ref SectionWriter class
deba@248
  1825
  ///
deba@248
  1826
  /// This function just returns a \ref SectionWriter class.
deba@248
  1827
  /// \relates SectionWriter
deba@645
  1828
  /// \sa sectionWriter(std::ostream& os)
deba@248
  1829
  inline SectionWriter sectionWriter(const char* fn) {
deba@248
  1830
    SectionWriter tmp(fn);
deba@248
  1831
    return tmp;
deba@248
  1832
  }
deba@127
  1833
}
deba@127
  1834
deba@127
  1835
#endif