src/lemon/graph_writer.h
author athos
Thu, 07 Apr 2005 15:22:03 +0000
changeset 1319 6e277ba3fc76
parent 1297 fde0d12545c1
child 1333 2640cf6547ff
permissions -rw-r--r--
Cplex interface has improved a lot.
deba@1137
     1
/* -*- C++ -*-
deba@1137
     2
 * src/lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library
deba@1137
     3
 *
alpar@1164
     4
 * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@1137
     5
 * (Egervary Combinatorial Optimization Research Group, EGRES).
deba@1137
     6
 *
deba@1137
     7
 * Permission to use, modify and distribute this software is granted
deba@1137
     8
 * provided that this copyright notice appears in all copies. For
deba@1137
     9
 * precise terms see the accompanying LICENSE file.
deba@1137
    10
 *
deba@1137
    11
 * This software is provided "AS IS" with no warranty of any kind,
deba@1137
    12
 * express or implied, and with no claim as to its suitability for any
deba@1137
    13
 * purpose.
deba@1137
    14
 *
deba@1137
    15
 */
deba@1137
    16
alpar@1287
    17
///\ingroup io_group
deba@1137
    18
///\file
alpar@1287
    19
///\brief Lemon Graph Format writer.
deba@1137
    20
deba@1214
    21
#ifndef LEMON_GRAPH_WRITER_H
deba@1214
    22
#define LEMON_GRAPH_WRITER_H
deba@1137
    23
deba@1137
    24
#include <iostream>
deba@1137
    25
#include <sstream>
deba@1137
    26
deba@1137
    27
#include <map>
deba@1137
    28
#include <vector>
deba@1137
    29
deba@1137
    30
#include <memory>
deba@1137
    31
deba@1208
    32
#include <lemon/map_utils.h>
deba@1214
    33
deba@1137
    34
#include <lemon/invalid.h>
deba@1137
    35
#include <lemon/error.h>
deba@1137
    36
deba@1137
    37
deba@1137
    38
namespace lemon {
deba@1137
    39
deba@1137
    40
  /// \brief Standard WriterTraits for the GraphWriter class.
deba@1137
    41
  ///
deba@1137
    42
  /// Standard WriterTraits for the GraphWriter class.
deba@1137
    43
  /// It defines standard writing method for all type of value. 
deba@1137
    44
  struct DefaultWriterTraits {
deba@1137
    45
deba@1137
    46
    /// \brief Template class for writing an value.
deba@1137
    47
    ///
deba@1137
    48
    /// Template class for writing an value.
deba@1137
    49
    template <typename _Value>
deba@1137
    50
    struct Writer {
deba@1137
    51
      /// The value type.
deba@1137
    52
      typedef _Value Value;
deba@1137
    53
deba@1188
    54
      /// \brief Writes a value to the given stream.
deba@1137
    55
      ///
deba@1188
    56
      /// Writes a value to the given stream.
deba@1137
    57
      void write(std::ostream& os, const Value& value) {
deba@1137
    58
	os << value << '\t';
deba@1137
    59
      }
deba@1137
    60
    };
deba@1137
    61
deba@1137
    62
  };
deba@1137
    63
deba@1137
    64
deba@1137
    65
  /// \brief Writer class for quoted strings.
deba@1137
    66
  ///
deba@1137
    67
  /// Writer class for quoted strings. It can process the escape
deba@1137
    68
  /// sequences in the string.
deba@1137
    69
  class QuotedStringWriter {
deba@1137
    70
  public:
deba@1137
    71
    typedef std::string Value;
deba@1137
    72
deba@1137
    73
    /// \brief Constructor for the writer.
deba@1137
    74
    ///
deba@1137
    75
    /// Constructor for the writer. If the given parameter is true
deba@1137
    76
    /// the writer creates escape sequences from special characters.
deba@1137
    77
    QuotedStringWriter(bool _escaped = true) : escaped(_escaped) {}
deba@1137
    78
deba@1188
    79
    /// \brief Writes a quoted string to the given stream.
deba@1137
    80
    ///
deba@1188
    81
    /// Writes a quoted string to the given stream.
deba@1137
    82
    void write(std::ostream& os, const std::string& value) {
deba@1137
    83
      os << "\"";
deba@1137
    84
      if (escaped) {
deba@1311
    85
	std::ostringstream ls;
deba@1137
    86
	for (int i = 0; i < (int)value.size(); ++i) {
deba@1137
    87
	  writeEscape(ls, value[i]);
deba@1137
    88
	}
deba@1137
    89
	os << ls.str();
deba@1137
    90
      } else {
deba@1137
    91
	os << value;
deba@1137
    92
      }
deba@1137
    93
      os << "\"";
deba@1137
    94
    }
deba@1137
    95
deba@1137
    96
  private:
deba@1137
    97
    
deba@1137
    98
    static void writeEscape(std::ostream& os, char c) {
deba@1137
    99
      switch (c) {
deba@1137
   100
      case '\\':
deba@1137
   101
	os << "\\\\";
deba@1137
   102
	return;
deba@1137
   103
      case '\"':
deba@1137
   104
	os << "\\\"";
deba@1137
   105
	return;
deba@1137
   106
      case '\'':
deba@1137
   107
	os << "\\\'";
deba@1137
   108
	return;
deba@1137
   109
      case '\?':
deba@1137
   110
	os << "\\\?";
deba@1137
   111
	return;
deba@1137
   112
      case '\a':
deba@1137
   113
	os << "\\a";
deba@1137
   114
	return;
deba@1137
   115
      case '\b':
deba@1137
   116
	os << "\\b";
deba@1137
   117
	return;
deba@1137
   118
      case '\f':
deba@1137
   119
	os << "\\f";
deba@1137
   120
	return;
deba@1137
   121
      case '\r':
deba@1137
   122
	os << "\\r";
deba@1137
   123
	return;
deba@1137
   124
      case '\n':
deba@1137
   125
	os << "\\n";
deba@1137
   126
	return;
deba@1137
   127
      case '\t':
deba@1137
   128
	os << "\\t";
deba@1137
   129
	return;
deba@1137
   130
      case '\v':
deba@1137
   131
	os << "\\v";
deba@1137
   132
	return;
deba@1137
   133
      default:
deba@1137
   134
	if (c < 0x20) {
deba@1311
   135
	  os << '\\' << std::oct << (int)c;
deba@1137
   136
	} else {
deba@1137
   137
	  os << c;
deba@1137
   138
	}
deba@1137
   139
	return;
deba@1137
   140
      }     
deba@1137
   141
    }
deba@1137
   142
  private:
deba@1137
   143
    bool escaped;
deba@1137
   144
  };
deba@1137
   145
deba@1137
   146
  
deba@1137
   147
  /// \brief The graph writer class.
deba@1137
   148
  ///
alpar@1287
   149
  ///\ingroup io_group
deba@1137
   150
  /// The writer class for the graph output.
alpar@1287
   151
  /// \see DefaultWriterTraits
alpar@1287
   152
  /// \see QuotedStringWriter
alpar@1138
   153
  /// \see \ref GraphReader
alpar@1138
   154
  /// \see \ref graph-io-page
deba@1137
   155
  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
deba@1137
   156
  class GraphWriter {
deba@1137
   157
  public:
deba@1137
   158
    
deba@1137
   159
    typedef _Graph Graph;
deba@1137
   160
    typedef typename Graph::Node Node;
deba@1137
   161
    typedef typename Graph::NodeIt NodeIt;
deba@1137
   162
    typedef typename Graph::Edge Edge;
deba@1137
   163
    typedef typename Graph::EdgeIt EdgeIt;
deba@1137
   164
deba@1137
   165
    typedef _WriterTraits WriterTraits;
deba@1137
   166
 
deba@1137
   167
    /// \brief Construct a new GraphWriter.
deba@1137
   168
    ///
deba@1137
   169
    /// Construct a new GraphWriter. It writes from the given map,
deba@1137
   170
    /// it constructs the given map and it use the given writer as the
deba@1137
   171
    /// default skipper.
deba@1208
   172
    GraphWriter(std::ostream& _os, const Graph& _graph) 
deba@1208
   173
      : os(_os), graph(_graph) {}
deba@1137
   174
deba@1137
   175
deba@1137
   176
    /// \brief Destruct the graph writer.
deba@1137
   177
    ///
deba@1137
   178
    /// Destruct the graph writer.
deba@1137
   179
    ~GraphWriter() {
deba@1137
   180
      for (typename NodeMapWriters::iterator it = node_map_writers.begin(); 
deba@1137
   181
	   it != node_map_writers.end(); ++it) {
deba@1137
   182
	delete it->second;
deba@1137
   183
      }
deba@1137
   184
deba@1137
   185
      for (typename EdgeMapWriters::iterator it = edge_map_writers.begin();
deba@1137
   186
	   it != edge_map_writers.end(); ++it) {
deba@1137
   187
	delete it->second;
deba@1137
   188
      }
deba@1137
   189
deba@1137
   190
    }
deba@1137
   191
deba@1137
   192
    // Node map rules
deba@1137
   193
deba@1137
   194
    /// \brief Add a new node map writer command for the writer.
deba@1137
   195
    ///
deba@1137
   196
    /// Add a new node map writer command for the writer.
deba@1137
   197
    template <typename Map>
deba@1137
   198
    GraphWriter& addNodeMap(std::string name, const Map& map) {
deba@1137
   199
      return addNodeMap<typename WriterTraits::template Writer<
deba@1137
   200
	typename Map::Value>, Map>(name, map);
deba@1137
   201
    }
deba@1137
   202
deba@1137
   203
    /// \brief Add a new node map writer command for the writer.
deba@1137
   204
    ///
deba@1137
   205
    /// Add a new node map writer command for the writer.
deba@1137
   206
    template <typename Writer, typename Map>
deba@1137
   207
    GraphWriter& addNodeMap(std::string name, const Map& map, 
deba@1137
   208
			      const Writer& writer = Writer()) {
deba@1137
   209
      node_map_writers.push_back(
deba@1137
   210
        make_pair(name, new MapWriter<Node, Map, Writer>(map, writer)));
deba@1137
   211
      return *this;
deba@1137
   212
    }
deba@1137
   213
deba@1137
   214
    // Edge map rules
deba@1137
   215
deba@1137
   216
    /// \brief Add a new edge map writer command for the writer.
deba@1137
   217
    ///
deba@1137
   218
    /// Add a new edge map writer command for the writer.
deba@1137
   219
    template <typename Map>
deba@1137
   220
    GraphWriter& addEdgeMap(std::string name, const Map& map) { 
deba@1137
   221
      return addEdgeMap<typename WriterTraits::template Writer<
deba@1137
   222
        typename Map::Value>, Map>(name, map);
deba@1137
   223
    }
deba@1137
   224
deba@1137
   225
deba@1137
   226
    /// \brief Add a new edge map writer command for the writer.
deba@1137
   227
    ///
deba@1137
   228
    /// Add a new edge map writer command for the writer.
deba@1137
   229
    template <typename Writer, typename Map>
deba@1137
   230
    GraphWriter& addEdgeMap(std::string name, 
deba@1137
   231
			    const Map& map, const Writer& writer = Writer()) {
deba@1137
   232
      edge_map_writers.push_back(make_pair(name, 
deba@1137
   233
	new MapWriter<Edge, Map, Writer>(map, writer)));
deba@1137
   234
      return *this;
deba@1137
   235
    }
deba@1137
   236
deba@1137
   237
    /// \brief Add a new labeled node writer for the writer.
deba@1137
   238
    ///
deba@1137
   239
    /// Add a new labeled node writer for the writer.
deba@1137
   240
    GraphWriter& addNode(std::string name, const Node& node) {
deba@1137
   241
      node_writers.push_back(make_pair(name, node));
deba@1137
   242
      return *this;
deba@1137
   243
    }
deba@1137
   244
deba@1137
   245
    /// \brief Add a new labeled edge writer for the writer.
deba@1137
   246
    ///
deba@1137
   247
    /// Add a new labeled edge writer for the writer.
deba@1137
   248
    GraphWriter& addEdge(std::string name, const Edge& edge) {
deba@1137
   249
      edge_writers.push_back(make_pair(name, edge));
deba@1137
   250
      return *this;
deba@1137
   251
    }
deba@1137
   252
deba@1137
   253
    /// \brief Executes the writer commands.
deba@1137
   254
    ///
deba@1137
   255
    /// Executes the writer commands.
deba@1137
   256
    void run() {   
deba@1137
   257
      writeNodeSet();
deba@1137
   258
      writeEdgeSet();
deba@1137
   259
      writeNodes();
deba@1137
   260
      writeEdges();
deba@1137
   261
      os << "@end" << std::endl;
deba@1137
   262
    }
deba@1137
   263
deba@1137
   264
  private:
deba@1137
   265
deba@1137
   266
    void writeNodeSet() {
deba@1137
   267
      if (node_map_writers.size() == 0) return;
deba@1137
   268
      os << "@nodeset" << std::endl;
deba@1137
   269
      for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1137
   270
	os << node_map_writers[i].first << '\t';
deba@1137
   271
      } 
deba@1137
   272
      os << std::endl;
deba@1137
   273
      for (NodeIt it(graph); it != INVALID; ++it) {
deba@1137
   274
	for (int i = 0; i < (int)node_map_writers.size(); ++i) {
deba@1137
   275
	  node_map_writers[i].second->write(os, it);
deba@1137
   276
	}
deba@1137
   277
	os << std::endl;
deba@1137
   278
      }
deba@1137
   279
deba@1137
   280
    }
deba@1137
   281
deba@1137
   282
    void writeEdgeSet() {
deba@1137
   283
      if (edge_map_writers.size() == 0) return;
deba@1137
   284
      if (node_map_writers.size() == 0) {
deba@1188
   285
	//	ErrorMessage message;
deba@1188
   286
	//	message << "Missing node id map";
deba@1188
   287
	//	throw IOLogicError(message);
deba@1137
   288
      }
deba@1137
   289
      os << "@edgeset" << std::endl;
deba@1137
   290
      os << "\t\t";
deba@1137
   291
      for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1137
   292
	os << edge_map_writers[i].first << '\t';
deba@1137
   293
      } 
deba@1137
   294
      os << std::endl;
deba@1137
   295
      for (EdgeIt it(graph); it != INVALID; ++it) {
deba@1137
   296
	node_map_writers[0].second->write(os, graph.source(it));
deba@1137
   297
	node_map_writers[0].second->write(os, graph.target(it));
deba@1137
   298
	for (int i = 0; i < (int)edge_map_writers.size(); ++i) {
deba@1137
   299
	  edge_map_writers[i].second->write(os, it);
deba@1137
   300
	}
deba@1137
   301
	os << std::endl;
deba@1137
   302
      }
deba@1137
   303
    }
deba@1137
   304
deba@1137
   305
    void writeNodes() {
deba@1137
   306
      if (node_writers.size() == 0) return;
deba@1137
   307
      if (node_map_writers.size() == 0) {
deba@1188
   308
	//	throw Exception() << "Missing node id map";
deba@1137
   309
      }
deba@1137
   310
      os << "@nodes" << std::endl;
deba@1137
   311
      for (int i = 0; i < (int)node_writers.size(); ++i) {
deba@1137
   312
	os << node_writers[i].first << '\t';
deba@1137
   313
	node_map_writers[0].second->write(os, node_writers[i].second);
deba@1137
   314
	os << std::endl;
deba@1137
   315
      } 
deba@1137
   316
    }
deba@1137
   317
deba@1137
   318
    void writeEdges() {
deba@1137
   319
      if (edge_writers.size() == 0) return;
deba@1137
   320
      if (edge_map_writers.size() == 0) {
deba@1188
   321
	//	throw Exception() << "Missing edge id map";
deba@1137
   322
      }
deba@1137
   323
      os << "@edges" << std::endl;
deba@1137
   324
      for (int i = 0; i < (int)edge_writers.size(); ++i) {
deba@1137
   325
	os << edge_writers[i].first << '\t';
deba@1137
   326
	edge_map_writers[0].second->write(os, edge_writers[i].second);
deba@1137
   327
	os << std::endl;
deba@1137
   328
      } 
deba@1137
   329
    }
deba@1137
   330
    
deba@1137
   331
    // Writers
deba@1137
   332
deba@1137
   333
    template <class _Item>
deba@1137
   334
    class WriterBase {
deba@1137
   335
    public:
deba@1137
   336
      typedef _Item Item;
deba@1137
   337
      virtual void write(std::ostream&, const Item&) = 0;
deba@1137
   338
    };
deba@1137
   339
deba@1137
   340
    template <class _Item, typename _Map, typename _Writer>
deba@1137
   341
    class MapWriter : public WriterBase<_Item> {
deba@1137
   342
    public:
deba@1137
   343
      typedef _Map Map;
deba@1137
   344
      typedef _Writer Writer;
deba@1137
   345
      typedef typename Writer::Value Value;
deba@1137
   346
      typedef _Item Item;
deba@1137
   347
      
deba@1137
   348
      const Map& map;
deba@1137
   349
      Writer writer;
deba@1137
   350
deba@1137
   351
      MapWriter(const Map& _map, const Writer& _writer) 
deba@1137
   352
	: map(_map), writer(_writer) {}
deba@1137
   353
deba@1137
   354
deba@1137
   355
      virtual void write(std::ostream& os, const Item& item) {
deba@1137
   356
	writer.write(os, map[item]);
deba@1137
   357
      }
deba@1137
   358
deba@1137
   359
    };
deba@1137
   360
deba@1137
   361
deba@1137
   362
deba@1137
   363
    typedef std::vector< std::pair<std::string, WriterBase<Node>*> > 
deba@1137
   364
      NodeMapWriters;
deba@1137
   365
    NodeMapWriters node_map_writers;
deba@1137
   366
deba@1137
   367
    typedef std::vector< std::pair<std::string, WriterBase<Edge>*> > 
deba@1137
   368
      EdgeMapWriters;
deba@1137
   369
    EdgeMapWriters edge_map_writers;
deba@1137
   370
deba@1137
   371
    typedef std::vector<std::pair<std::string, Node> > NodeWriters;
deba@1137
   372
    NodeWriters node_writers;
deba@1137
   373
deba@1137
   374
    typedef std::vector<std::pair<std::string, Edge> > EdgeWriters;
deba@1137
   375
    EdgeWriters edge_writers;
deba@1137
   376
deba@1137
   377
    std::ostream& os;
deba@1208
   378
    const Graph& graph;
deba@1137
   379
deba@1137
   380
  };
deba@1137
   381
deba@1208
   382
  /// Ready to use writer function.  
deba@1208
   383
  template<typename Graph, typename CapacityMap, typename CostMap>
deba@1208
   384
  void writeGraph(std::ostream& os, const Graph &g, 
deba@1208
   385
		  const CapacityMap& capacity, const typename Graph::Node &s,
deba@1208
   386
		  const typename Graph::Node &t, const CostMap& cost) {
deba@1208
   387
    GraphWriter<Graph> reader(os, g);
deba@1208
   388
    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
deba@1208
   389
    reader.addNodeMap("id", nodeIdMap);
deba@1208
   390
    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
deba@1208
   391
    reader.addEdgeMap("id", edgeIdMap);
deba@1208
   392
    reader.addEdgeMap("capacity", capacity);
deba@1208
   393
    reader.addEdgeMap("cost", cost);
deba@1208
   394
    reader.addNode("source", s);
deba@1208
   395
    reader.addNode("target", t);
deba@1208
   396
    reader.run();
deba@1208
   397
  }
deba@1208
   398
deba@1208
   399
  /// Ready to use writer function.  
deba@1297
   400
  template<typename Graph, typename CapacityMap>
deba@1208
   401
  void writeGraph(std::ostream& os, const Graph &g, 
deba@1208
   402
		  const CapacityMap& capacity, const typename Graph::Node &s,
deba@1208
   403
		  const typename Graph::Node &t) {
deba@1208
   404
    GraphWriter<Graph> reader(os, g);
deba@1208
   405
    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
deba@1208
   406
    reader.addNodeMap("id", nodeIdMap);
deba@1208
   407
    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
deba@1208
   408
    reader.addEdgeMap("id", edgeIdMap);
deba@1208
   409
    reader.addEdgeMap("capacity", capacity);
deba@1208
   410
    reader.addNode("source", s);
deba@1208
   411
    reader.addNode("target", t);
deba@1208
   412
    reader.run();
deba@1208
   413
  }
deba@1208
   414
deba@1208
   415
  /// Ready to use writer function.  
deba@1208
   416
  template<typename Graph, typename CapacityMap>
deba@1208
   417
  void writeGraph(std::ostream& os, const Graph &g, 
deba@1208
   418
		  const CapacityMap& capacity, const typename Graph::Node &s) {
deba@1208
   419
    GraphWriter<Graph> reader(os, g);
deba@1208
   420
    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
deba@1208
   421
    reader.addNodeMap("id", nodeIdMap);
deba@1208
   422
    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
deba@1208
   423
    reader.addEdgeMap("id", edgeIdMap);
deba@1208
   424
    reader.addEdgeMap("capacity", capacity);
deba@1208
   425
    reader.addNode("source", s);
deba@1208
   426
    reader.run();
deba@1208
   427
  }
deba@1208
   428
  /// Ready to use writer function.  
deba@1208
   429
  template<typename Graph, typename CapacityMap>
deba@1208
   430
  void writeGraph(std::ostream& os, const Graph &g, 
deba@1208
   431
		  const CapacityMap& capacity) {
deba@1208
   432
    GraphWriter<Graph> reader(os, g);
deba@1208
   433
    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
deba@1208
   434
    reader.addNodeMap("id", nodeIdMap);
deba@1208
   435
    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
deba@1208
   436
    reader.addEdgeMap("id", edgeIdMap);
deba@1208
   437
    reader.addEdgeMap("capacity", capacity);
deba@1208
   438
    reader.run();
deba@1208
   439
  }
deba@1208
   440
  /// Ready to use writer function.  
deba@1208
   441
  template<typename Graph>
deba@1208
   442
  void writeGraph(std::ostream& os, const Graph &g) {
deba@1208
   443
    GraphWriter<Graph> reader(os, g);
deba@1208
   444
    IdMap<Graph, typename Graph::Node> nodeIdMap(g);
deba@1208
   445
    reader.addNodeMap("id", nodeIdMap);
deba@1208
   446
    IdMap<Graph, typename Graph::Edge> edgeIdMap(g);
deba@1208
   447
    reader.addEdgeMap("id", edgeIdMap);
deba@1208
   448
    reader.run();
deba@1208
   449
  }
deba@1208
   450
deba@1137
   451
deba@1137
   452
}
deba@1214
   453
deba@1214
   454
#endif