BpUGraphReader and Writer
authordeba
Wed, 24 Oct 2007 16:31:49 +0000
changeset 25029c23c3762bc5
parent 2501 1af977819111
child 2503 15b3bf0141c7
BpUGraphReader and Writer
doc/graph_io.dox
lemon/graph_reader.h
lemon/graph_writer.h
lemon/lemon_reader.h
lemon/lemon_writer.h
     1.1 --- a/doc/graph_io.dox	Sat Oct 20 14:29:12 2007 +0000
     1.2 +++ b/doc/graph_io.dox	Wed Oct 24 16:31:49 2007 +0000
     1.3 @@ -335,7 +335,7 @@
     1.4  
     1.5  The specialization of writing is very similar to that of reading.
     1.6  
     1.7 -\section u Undirected graphs
     1.8 +\section undir Undirected and Bipartite graphs
     1.9  
    1.10  In a file describing an undirected graph (ugraph, for short) you find an
    1.11  \c uedgeset section instead of the \c edgeset section. The first line of
    1.12 @@ -343,9 +343,9 @@
    1.13  next lines describe one undirected edge with the the incident nodes and the
    1.14  values of the map.
    1.15  
    1.16 -The format handles directed edge maps as a syntactical sugar???, if there
    1.17 -are two maps with names being the same with a \c '+' and a \c '-' prefix
    1.18 -then this will be read as a directed map.
    1.19 +The format could store directed edge maps, if there are two maps with 
    1.20 +names being the same with a \c '+' and a \c '-' prefix then this could 
    1.21 +be read as such a map.
    1.22  
    1.23  \code
    1.24  @uedgeset
    1.25 @@ -386,6 +386,35 @@
    1.26  reader.readEdge("edge", edge);
    1.27  \endcode
    1.28  
    1.29 +The undirected bipartite graphs could be read with the \c BpUGraph
    1.30 +class and it has specialized nodeset section, which should be start
    1.31 +with \c "@bpnodeset". This section is separated to two
    1.32 +subsections. The header line of these sections start with "&anodeset"
    1.33 +or "&bnodeset" and after that the line contains the names of the
    1.34 +regular and A-node or B-node maps accordingly. The lines of each
    1.35 +section contains the mapped values. The labels of the graph should be
    1.36 +unique overall both subsections.
    1.37 +
    1.38 +\code
    1.39 +@bpnodeset
    1.40 +&anodeset label   coords	radius
    1.41 +	  0       (0, 0)	14.0
    1.42 +	  1       (0, 1)	12.0
    1.43 +&bnodeset label	  coords
    1.44 +	  2       (1, 0)
    1.45 +	  3       (1, 1)
    1.46 +\endcode
    1.47 +
    1.48 +The reading can be done with \ref lemon::BpUGraphReader::readANodeMap() 
    1.49 +"readANodeMap()", \ref lemon::BpUGraphReader::readBNodeMap() 
    1.50 +"readBNodeMap()" or \ref lemon::BpUGraphReader::readNodeMap() 
    1.51 +"readNodeMap()" members.
    1.52 +
    1.53 +\code
    1.54 +reader.readNodeMap("coords", coords);
    1.55 +reader.readAnodeMap("radius", radius);
    1.56 +\endcode
    1.57 +
    1.58  \section advanced Advanced features
    1.59  
    1.60  The graph reader and writer classes give an easy way to read and write
     2.1 --- a/lemon/graph_reader.h	Sat Oct 20 14:29:12 2007 +0000
     2.2 +++ b/lemon/graph_reader.h	Wed Oct 24 16:31:49 2007 +0000
     2.3 @@ -725,6 +725,469 @@
     2.4      AttributeReader<ReaderTraits> attribute_reader;
     2.5    };
     2.6  
     2.7 +  /// \brief The bipartite graph reader class.
     2.8 +  ///
     2.9 +  /// The \c BpUGraphReader class provides the graph input. 
    2.10 +  /// Before you read this documentation it might be useful to read the general
    2.11 +  /// description of  \ref graph-io-page "Graph Input-Output".
    2.12 +  ///
    2.13 +  /// The given file format may contain several maps and labeled nodes or 
    2.14 +  /// edges.
    2.15 +  ///
    2.16 +  /// If you read a graph you need not read all the maps and items just those
    2.17 +  /// that you need. The interface of the \c BpUGraphReader is very similar
    2.18 +  /// to the BpUGraphWriter but the reading method does not depend on the
    2.19 +  /// order of the given commands.
    2.20 +  ///
    2.21 +  /// The reader object suppose that each not read value does not contain 
    2.22 +  /// whitespaces, therefore it has some extra possibilities to control how
    2.23 +  /// it should skip the values when the string representation contains spaces.
    2.24 +  ///
    2.25 +  ///\code
    2.26 +  /// BpUGraphReader<ListBpUGraph> reader(std::cin, graph);
    2.27 +  ///\endcode
    2.28 +  ///
    2.29 +  /// The \c readANodeMap() function reads a map from the A-part of
    2.30 +  /// the\c \@bpnodeset section, while the \c readBNodeMap() reads
    2.31 +  /// from the B-part of the section.  If you use the \c readNodeMap()
    2.32 +  /// function, then the given map should appear in both part of the
    2.33 +  /// section. If there is a map that you do not want to read from the
    2.34 +  /// file and there is whitespace in the string represenation of the
    2.35 +  /// values then you should call the \c skipANodeMap(), \c
    2.36 +  /// skipBNodeMap() or \c skipNodeMap() template member function with
    2.37 +  /// proper parameters.
    2.38 +  ///
    2.39 +  ///\code
    2.40 +  /// reader.readNodeMap("coords", coords);
    2.41 +  /// reader.readANodeMap("range", range);
    2.42 +  /// reader.readANodeMap("benefit", benefit);
    2.43 +  ///
    2.44 +  /// reader.skipNodeMap("description", desc);
    2.45 +  ///
    2.46 +  /// reader.readNodeMap("color", colorMap);
    2.47 +  ///\endcode
    2.48 +  ///
    2.49 +  /// With the \c readUEdgeMap() member function you can give an 
    2.50 +  /// uedge map reading command similar to the NodeMaps. 
    2.51 +  ///
    2.52 +  ///\code
    2.53 +  /// reader.readUEdgeMap("capacity", capacityMap);
    2.54 +  /// reader.readEdgeMap("flow", flowMap);
    2.55 +  ///\endcode 
    2.56 +  ///
    2.57 +  /// With \c readNode() and \c readUEdge() functions you can read 
    2.58 +  /// labeled Nodes and UEdges.
    2.59 +  ///
    2.60 +  ///\code
    2.61 +  /// reader.readNode("source", sourceNode);
    2.62 +  /// reader.readNode("target", targetNode);
    2.63 +  ///
    2.64 +  /// reader.readUEdge("observed", uEdge);
    2.65 +  ///\endcode
    2.66 +  ///
    2.67 +  /// With the \c readAttribute() functions you can read an attribute
    2.68 +  /// in a variable. You can specify the reader for the attribute as
    2.69 +  /// the nodemaps.
    2.70 +  ///
    2.71 +  /// After you give all read commands you must call the \c run() member
    2.72 +  /// function, which execute all the commands.
    2.73 +  ///
    2.74 +  ///\code
    2.75 +  /// reader.run();
    2.76 +  ///\endcode
    2.77 +  ///
    2.78 +  /// \see GraphReader
    2.79 +  /// \see DefaultReaderTraits
    2.80 +  /// \see \ref UGraphWriter
    2.81 +  /// \see \ref graph-io-page
    2.82 +  ///
    2.83 +  /// \author Balazs Dezso
    2.84 +  template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits> 
    2.85 +  class BpUGraphReader {
    2.86 +  public:
    2.87 +    
    2.88 +    typedef _Graph Graph;
    2.89 +    typedef typename Graph::Node Node;
    2.90 +    typedef typename Graph::Edge Edge;
    2.91 +    typedef typename Graph::UEdge UEdge;
    2.92 +
    2.93 +    typedef _ReaderTraits ReaderTraits;
    2.94 +    typedef typename ReaderTraits::Skipper DefaultSkipper;
    2.95 +
    2.96 +    /// \brief Construct a new BpUGraphReader.
    2.97 +    ///
    2.98 +    /// Construct a new BpUGraphReader. It reads into the given graph
    2.99 +    /// and it use the given reader as the default skipper.
   2.100 +    BpUGraphReader(std::istream& _is, Graph& _graph, 
   2.101 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   2.102 +      : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
   2.103 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   2.104 +	uedgeset_reader(*reader, _graph, nodeset_reader, 
   2.105 +			     std::string(), skipper),
   2.106 +	node_reader(*reader, nodeset_reader, std::string()),
   2.107 +	uedge_reader(*reader, uedgeset_reader, std::string()),
   2.108 +	attribute_reader(*reader, std::string()) {}
   2.109 +
   2.110 +    /// \brief Construct a new BpUGraphReader.
   2.111 +    ///
   2.112 +    /// Construct a new BpUGraphReader. It reads into the given graph
   2.113 +    /// and it use the given reader as the default skipper.
   2.114 +    BpUGraphReader(const std::string& _filename, Graph& _graph, 
   2.115 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   2.116 +      : reader(new LemonReader(_filename)), own_reader(true), 
   2.117 +	skipper(_skipper),
   2.118 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   2.119 +	uedgeset_reader(*reader, _graph, nodeset_reader, 
   2.120 +			     std::string(), skipper),
   2.121 +	node_reader(*reader, nodeset_reader, std::string()),
   2.122 +	uedge_reader(*reader, uedgeset_reader, std::string()),
   2.123 +	attribute_reader(*reader, std::string()) {}
   2.124 +
   2.125 +    /// \brief Construct a new BpUGraphReader.
   2.126 +    ///
   2.127 +    /// Construct a new BpUGraphReader. It reads into the given graph
   2.128 +    /// and it use the given reader as the default skipper.
   2.129 +    BpUGraphReader(LemonReader& _reader, Graph& _graph, 
   2.130 +		     const DefaultSkipper& _skipper = DefaultSkipper()) 
   2.131 +      : reader(_reader), own_reader(false), skipper(_skipper),
   2.132 +	nodeset_reader(*reader, _graph, std::string(), skipper),
   2.133 +	uedgeset_reader(*reader, _graph, nodeset_reader, 
   2.134 +			     std::string(), skipper),
   2.135 +	node_reader(*reader, nodeset_reader, std::string()),
   2.136 +	uedge_reader(*reader, uedgeset_reader, std::string()),
   2.137 +	attribute_reader(*reader, std::string()) {}
   2.138 +
   2.139 +    /// \brief Destruct the graph reader.
   2.140 +    ///
   2.141 +    /// Destruct the graph reader.
   2.142 +    ~BpUGraphReader() {
   2.143 +      if (own_reader) 
   2.144 +	delete reader;
   2.145 +    }
   2.146 +
   2.147 +    /// \brief Give a new node map reading command to the reader.
   2.148 +    ///
   2.149 +    /// Give a new node map reading command to the reader.
   2.150 +    template <typename Map>
   2.151 +    BpUGraphReader& readNodeMap(std::string name, Map& map) {
   2.152 +      nodeset_reader.readNodeMap(name, map);
   2.153 +      return *this;
   2.154 +    }
   2.155 +
   2.156 +    template <typename Map>
   2.157 +    BpUGraphReader& readNodeMap(std::string name, const Map& map) {
   2.158 +      nodeset_reader.readNodeMap(name, map);
   2.159 +      return *this;
   2.160 +    }
   2.161 +
   2.162 +    /// \brief Give a new node map reading command to the reader.
   2.163 +    ///
   2.164 +    /// Give a new node map reading command to the reader.
   2.165 +    template <typename ItemReader, typename Map>
   2.166 +    BpUGraphReader& readNodeMap(std::string name, Map& map, 
   2.167 +                              const ItemReader& ir = ItemReader()) {
   2.168 +      nodeset_reader.readNodeMap(name, map, ir);
   2.169 +      return *this;
   2.170 +    }
   2.171 +
   2.172 +    template <typename ItemReader, typename Map>
   2.173 +    BpUGraphReader& readNodeMap(std::string name, const Map& map, 
   2.174 +                              const ItemReader& ir = ItemReader()) {
   2.175 +      nodeset_reader.readNodeMap(name, map, ir);
   2.176 +      return *this;
   2.177 +    }
   2.178 +
   2.179 +    /// \brief Give a new node map skipping command to the reader.
   2.180 +    ///
   2.181 +    /// Give a new node map skipping command to the reader.
   2.182 +    template <typename ItemReader>
   2.183 +    BpUGraphReader& skipNodeMap(std::string name, 
   2.184 +                              const ItemReader& ir = ItemReader()) {
   2.185 +      nodeset_reader.skipNodeMap(name, ir);
   2.186 +      return *this;
   2.187 +    }
   2.188 +
   2.189 +    /// \brief Give a new A-node map reading command to the reader.
   2.190 +    ///
   2.191 +    /// Give a new A-node map reading command to the reader.
   2.192 +    template <typename Map>
   2.193 +    BpUGraphReader& readANodeMap(std::string name, Map& map) {
   2.194 +      nodeset_reader.readANodeMap(name, map);
   2.195 +      return *this;
   2.196 +    }
   2.197 +
   2.198 +    template <typename Map>
   2.199 +    BpUGraphReader& readANodeMap(std::string name, const Map& map) {
   2.200 +      nodeset_reader.readANodeMap(name, map);
   2.201 +      return *this;
   2.202 +    }
   2.203 +
   2.204 +    /// \brief Give a new A-node map reading command to the reader.
   2.205 +    ///
   2.206 +    /// Give a new A-node map reading command to the reader.
   2.207 +    template <typename ItemReader, typename Map>
   2.208 +    BpUGraphReader& readANodeMap(std::string name, Map& map, 
   2.209 +                              const ItemReader& ir = ItemReader()) {
   2.210 +      nodeset_reader.readANodeMap(name, map, ir);
   2.211 +      return *this;
   2.212 +    }
   2.213 +
   2.214 +    template <typename ItemReader, typename Map>
   2.215 +    BpUGraphReader& readANodeMap(std::string name, const Map& map, 
   2.216 +                              const ItemReader& ir = ItemReader()) {
   2.217 +      nodeset_reader.readNodeMap(name, map, ir);
   2.218 +      return *this;
   2.219 +    }
   2.220 +
   2.221 +    /// \brief Give a new A-node map skipping command to the reader.
   2.222 +    ///
   2.223 +    /// Give a new A-node map skipping command to the reader.
   2.224 +    template <typename ItemReader>
   2.225 +    BpUGraphReader& skipANodeMap(std::string name, 
   2.226 +                              const ItemReader& ir = ItemReader()) {
   2.227 +      nodeset_reader.skipANodeMap(name, ir);
   2.228 +      return *this;
   2.229 +    }
   2.230 +
   2.231 +    /// \brief Give a new B-node map reading command to the reader.
   2.232 +    ///
   2.233 +    /// Give a new B-node map reading command to the reader.
   2.234 +    template <typename Map>
   2.235 +    BpUGraphReader& readBNodeMap(std::string name, Map& map) {
   2.236 +      nodeset_reader.readBNodeMap(name, map);
   2.237 +      return *this;
   2.238 +    }
   2.239 +
   2.240 +    template <typename Map>
   2.241 +    BpUGraphReader& readBNodeMap(std::string name, const Map& map) {
   2.242 +      nodeset_reader.readBNodeMap(name, map);
   2.243 +      return *this;
   2.244 +    }
   2.245 +
   2.246 +    /// \brief Give a new B-node map reading command to the reader.
   2.247 +    ///
   2.248 +    /// Give a new B-node map reading command to the reader.
   2.249 +    template <typename ItemReader, typename Map>
   2.250 +    BpUGraphReader& readBNodeMap(std::string name, Map& map, 
   2.251 +                              const ItemReader& ir = ItemReader()) {
   2.252 +      nodeset_reader.readBNodeMap(name, map, ir);
   2.253 +      return *this;
   2.254 +    }
   2.255 +
   2.256 +    template <typename ItemReader, typename Map>
   2.257 +    BpUGraphReader& readBNodeMap(std::string name, const Map& map, 
   2.258 +                              const ItemReader& ir = ItemReader()) {
   2.259 +      nodeset_reader.readNodeMap(name, map, ir);
   2.260 +      return *this;
   2.261 +    }
   2.262 +
   2.263 +    /// \brief Give a new B-node map skipping command to the reader.
   2.264 +    ///
   2.265 +    /// Give a new B-node map skipping command to the reader.
   2.266 +    template <typename ItemReader>
   2.267 +    BpUGraphReader& skipBNodeMap(std::string name, 
   2.268 +                              const ItemReader& ir = ItemReader()) {
   2.269 +      nodeset_reader.skipBNodeMap(name, ir);
   2.270 +      return *this;
   2.271 +    }
   2.272 +
   2.273 +    /// \brief Give a new undirected edge map reading command to the reader.
   2.274 +    ///
   2.275 +    /// Give a new undirected edge map reading command to the reader.
   2.276 +    template <typename Map>
   2.277 +    BpUGraphReader& readUEdgeMap(std::string name, Map& map) { 
   2.278 +      uedgeset_reader.readUEdgeMap(name, map);
   2.279 +      return *this;
   2.280 +    }
   2.281 +
   2.282 +    template <typename Map>
   2.283 +    BpUGraphReader& readUEdgeMap(std::string name, const Map& map) { 
   2.284 +      uedgeset_reader.readUEdgeMap(name, map);
   2.285 +      return *this;
   2.286 +    }
   2.287 +
   2.288 +
   2.289 +    /// \brief Give a new undirected edge map reading command to the reader.
   2.290 +    ///
   2.291 +    /// Give a new undirected edge map reading command to the reader.
   2.292 +    template <typename ItemReader, typename Map>
   2.293 +    BpUGraphReader& readUEdgeMap(std::string name, Map& map,
   2.294 +                               const ItemReader& ir = ItemReader()) {
   2.295 +      uedgeset_reader.readUEdgeMap(name, map, ir);
   2.296 +      return *this;
   2.297 +    }
   2.298 +
   2.299 +    template <typename ItemReader, typename Map>
   2.300 +    BpUGraphReader& readUEdgeMap(std::string name, const Map& map,
   2.301 +                               const ItemReader& ir = ItemReader()) {
   2.302 +      uedgeset_reader.readUEdgeMap(name, map, ir);
   2.303 +      return *this;
   2.304 +    }
   2.305 +
   2.306 +    /// \brief Give a new undirected edge map skipping command to the reader.
   2.307 +    ///
   2.308 +    /// Give a new undirected edge map skipping command to the reader.
   2.309 +    template <typename ItemReader>
   2.310 +    BpUGraphReader& skipUEdgeMap(std::string name,
   2.311 +				       const ItemReader& ir = ItemReader()) {
   2.312 +      uedgeset_reader.skipUMap(name, ir);
   2.313 +      return *this;
   2.314 +    }
   2.315 +
   2.316 +
   2.317 +    /// \brief Give a new edge map reading command to the reader.
   2.318 +    ///
   2.319 +    /// Give a new edge map reading command to the reader.
   2.320 +    template <typename Map>
   2.321 +    BpUGraphReader& readEdgeMap(std::string name, Map& map) { 
   2.322 +      uedgeset_reader.readEdgeMap(name, map);
   2.323 +      return *this;
   2.324 +    }
   2.325 +
   2.326 +    template <typename Map>
   2.327 +    BpUGraphReader& readEdgeMap(std::string name, const Map& map) { 
   2.328 +      uedgeset_reader.readEdgeMap(name, map);
   2.329 +      return *this;
   2.330 +    }
   2.331 +
   2.332 +
   2.333 +    /// \brief Give a new edge map reading command to the reader.
   2.334 +    ///
   2.335 +    /// Give a new edge map reading command to the reader.
   2.336 +    template <typename ItemReader, typename Map>
   2.337 +    BpUGraphReader& readEdgeMap(std::string name, Map& map,
   2.338 +                              const ItemReader& ir = ItemReader()) {
   2.339 +      uedgeset_reader.readEdgeMap(name, map, ir);
   2.340 +      return *this;
   2.341 +    }
   2.342 +
   2.343 +    template <typename ItemReader, typename Map>
   2.344 +    BpUGraphReader& readEdgeMap(std::string name, const Map& map,
   2.345 +                              const ItemReader& ir = ItemReader()) {
   2.346 +      uedgeset_reader.readEdgeMap(name, map, ir);
   2.347 +      return *this;
   2.348 +    }
   2.349 +
   2.350 +    /// \brief Give a new edge map skipping command to the reader.
   2.351 +    ///
   2.352 +    /// Give a new edge map skipping command to the reader.
   2.353 +    template <typename ItemReader>
   2.354 +    BpUGraphReader& skipEdgeMap(std::string name,
   2.355 +                              const ItemReader& ir = ItemReader()) {
   2.356 +      uedgeset_reader.skipEdgeMap(name, ir);
   2.357 +      return *this;
   2.358 +    }
   2.359 +
   2.360 +    /// \brief Give a new labeled node reading command to the reader.
   2.361 +    ///
   2.362 +    /// Give a new labeled node reading command to the reader.
   2.363 +    BpUGraphReader& readNode(std::string name, Node& node) {
   2.364 +      node_reader.readNode(name, node);
   2.365 +      return *this;
   2.366 +    }
   2.367 +
   2.368 +    /// \brief Give a new labeled edge reading command to the reader.
   2.369 +    ///
   2.370 +    /// Give a new labeled edge reading command to the reader.
   2.371 +    BpUGraphReader& readEdge(std::string name, Edge& edge) {
   2.372 +      uedge_reader.readEdge(name, edge);
   2.373 +    }
   2.374 +
   2.375 +    /// \brief Give a new labeled undirected edge reading command to the
   2.376 +    /// reader.
   2.377 +    ///
   2.378 +    /// Give a new labeled undirected edge reading command to the reader.
   2.379 +    BpUGraphReader& readUEdge(std::string name, UEdge& edge) {
   2.380 +      uedge_reader.readUEdge(name, edge);
   2.381 +    }
   2.382 +
   2.383 +    /// \brief Give a new attribute reading command.
   2.384 +    ///
   2.385 +    ///  Give a new attribute reading command.
   2.386 +    template <typename Value>
   2.387 +    BpUGraphReader& readAttribute(std::string name, Value& value) {
   2.388 +      attribute_reader.readAttribute(name, value);
   2.389 +      return *this;
   2.390 +    }
   2.391 +    
   2.392 +    /// \brief Give a new attribute reading command.
   2.393 +    ///
   2.394 +    ///  Give a new attribute reading command.
   2.395 +    template <typename ItemReader, typename Value>
   2.396 +    BpUGraphReader& readAttribute(std::string name, Value& value, 
   2.397 +			       const ItemReader& ir = ItemReader()) {
   2.398 +      attribute_reader.readAttribute(name, value, ir);
   2.399 +      return *this;
   2.400 +    }
   2.401 +
   2.402 +    /// \brief Conversion operator to LemonReader.
   2.403 +    ///
   2.404 +    /// Conversion operator to LemonReader. It make possible
   2.405 +    /// to access the encapsulated \e LemonReader, this way
   2.406 +    /// you can attach to this reader new instances of 
   2.407 +    /// \e LemonReader::SectionReader.
   2.408 +    operator LemonReader&() {
   2.409 +      return *reader;
   2.410 +    }
   2.411 +
   2.412 +    /// \brief Executes the reading commands.
   2.413 +    ///
   2.414 +    /// Executes the reading commands.
   2.415 +    void run() {
   2.416 +      reader->run();
   2.417 +    }
   2.418 +
   2.419 +
   2.420 +    /// \brief Returns true if the reader can give back the items by its label.
   2.421 +    ///
   2.422 +    /// Returns true if the reader can give back the items by its label.
   2.423 +    bool isLabelReader() const {
   2.424 +      return nodeset_reader.isLabelReader() && 
   2.425 +        uedgeset_reader.isLabelReader();
   2.426 +    }
   2.427 +
   2.428 +    /// \brief Gives back the node by its label.
   2.429 +    ///
   2.430 +    /// It reads an label from the stream and gives back which node belongs to
   2.431 +    /// it. It is possible only if there was read a "label" named node map.
   2.432 +    void readLabel(std::istream& is, Node& node) const {
   2.433 +      return nodeset_reader.readLabel(is, node);
   2.434 +    } 
   2.435 +
   2.436 +    /// \brief Gives back the edge by its label
   2.437 +    ///
   2.438 +    /// It reads an label from the stream and gives back which edge belongs to
   2.439 +    /// it. It is possible only if there was read a "label" named edge map.
   2.440 +    void readLabel(std::istream& is, Edge& edge) const {
   2.441 +      return uedgeset_reader.readLabel(is, edge);
   2.442 +    } 
   2.443 +
   2.444 +    /// \brief Gives back the undirected edge by its label.
   2.445 +    ///
   2.446 +    /// It reads an label from the stream and gives back which undirected edge 
   2.447 +    /// belongs to it. It is possible only if there was read a "label" named 
   2.448 +    /// edge map.
   2.449 +    void readLabel(std::istream& is, UEdge& uedge) const {
   2.450 +      return uedgeset_reader.readLabel(is, uedge);
   2.451 +    } 
   2.452 +    
   2.453 +
   2.454 +  private:
   2.455 +
   2.456 +    LemonReader* reader;
   2.457 +    bool own_reader;
   2.458 +
   2.459 +    DefaultSkipper skipper;
   2.460 +
   2.461 +    BpNodeSetReader<Graph, ReaderTraits> nodeset_reader;
   2.462 +    UEdgeSetReader<Graph, ReaderTraits> uedgeset_reader;
   2.463 +
   2.464 +    NodeReader<Graph> node_reader;
   2.465 +    UEdgeReader<Graph> uedge_reader;
   2.466 +    
   2.467 +    AttributeReader<ReaderTraits> attribute_reader;
   2.468 +  };
   2.469 +
   2.470  
   2.471    /// @}
   2.472  }
     3.1 --- a/lemon/graph_writer.h	Sat Oct 20 14:29:12 2007 +0000
     3.2 +++ b/lemon/graph_writer.h	Wed Oct 24 16:31:49 2007 +0000
     3.3 @@ -156,7 +156,7 @@
     3.4  
     3.5      /// \brief Issue a new node map writing command for the writer.
     3.6      ///
     3.7 -   /// This function issues a new <i> node map writing command</i> to the writer.
     3.8 +    /// This function issues a new <i> node map writing command</i> to the writer.
     3.9      template <typename Map>
    3.10      GraphWriter& writeNodeMap(std::string label, const Map& map) {
    3.11        nodeset_writer.writeNodeMap(label, map);
    3.12 @@ -166,7 +166,7 @@
    3.13  
    3.14      /// \brief Issue a new node map writing command for the writer.
    3.15      ///
    3.16 -   /// This function issues a new <i> node map writing command</i> to the writer.
    3.17 +    /// This function issues a new <i> node map writing command</i> to the writer.
    3.18      template <typename ItemWriter, typename Map>
    3.19      GraphWriter& writeNodeMap(std::string label, const Map& map, 
    3.20  			      const ItemWriter& iw = ItemWriter()) {
    3.21 @@ -639,6 +639,376 @@
    3.22      AttributeWriter<WriterTraits> attribute_writer;
    3.23    };
    3.24  
    3.25 +  /// \brief The bipartite graph writer class.
    3.26 +  ///
    3.27 +  /// The \c BpUGraphWriter class provides the ugraph output. To write 
    3.28 +  /// a graph you should first give writing commands to the writer. You can 
    3.29 +  /// declare write command as \c NodeMap, \c EdgeMap or \c UEdgeMap 
    3.30 +  /// writing and labeled Node, Edge or UEdge writing.
    3.31 +  ///
    3.32 +  ///\code
    3.33 +  /// BpUGraphWriter<ListUGraph> writer(std::cout, graph);
    3.34 +  ///\endcode
    3.35 +  ///
    3.36 +  /// The \c writeNodeMap() function declares a \c NodeMap writing 
    3.37 +  /// command in the \c BpUGraphWriter. You should give as parameter 
    3.38 +  /// the name of the map and the map object. The NodeMap writing 
    3.39 +  /// command with name "label" should write a unique map because it 
    3.40 +  /// is regarded as label map.
    3.41 +  ///
    3.42 +  ///\code
    3.43 +  /// IdMap<ListUGraph, Node> nodeLabelMap;
    3.44 +  /// writer.writeNodeMap("label", nodeLabelMap);
    3.45 +  ///
    3.46 +  /// writer.writeNodeMap("coords", coords);
    3.47 +  /// writer.writeNodeMap("color", colorMap);
    3.48 +  ///\endcode
    3.49 +  ///
    3.50 +  /// With the \c writeUEdgeMap() member function you can give an 
    3.51 +  /// undirected edge map writing command similar to the NodeMaps.
    3.52 +  ///
    3.53 +  ///\code
    3.54 +  /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> > 
    3.55 +  ///   edgeDescMap(graph);
    3.56 +  /// writer.writeUEdgeMap("descriptor", edgeDescMap);
    3.57 +  ///
    3.58 +  /// writer.writeUEdgeMap("weight", weightMap);
    3.59 +  /// writer.writeUEdgeMap("label", labelMap);
    3.60 +  ///\endcode
    3.61 +  /// 
    3.62 +  /// The EdgeMap handling is just a syntactical sugar. It writes
    3.63 +  /// two undirected edge map with '+' and '-' prefix in the name.
    3.64 +  ///
    3.65 +  ///\code
    3.66 +  /// writer.writeEdgeMap("capacity", capacityMap);
    3.67 +  ///\endcode
    3.68 +  ///
    3.69 +  ///
    3.70 +  /// With \c writeNode() and \c writeUEdge() functions you can 
    3.71 +  /// designate nodes and undirected edges in the graph. For example, you can 
    3.72 +  /// write out the source and target of the graph.
    3.73 +  ///
    3.74 +  ///\code
    3.75 +  /// writer.writeNode("source", sourceNode);
    3.76 +  /// writer.writeNode("target", targetNode);
    3.77 +  ///
    3.78 +  /// writer.writeUEdge("observed", uEdge);
    3.79 +  ///\endcode
    3.80 +  ///
    3.81 +  /// After you give all write commands you must call the \c run() member
    3.82 +  /// function, which executes all the writing commands.
    3.83 +  ///
    3.84 +  ///\code
    3.85 +  /// writer.run();
    3.86 +  ///\endcode
    3.87 +  ///
    3.88 +  /// \see DefaultWriterTraits
    3.89 +  /// \see QuotedStringWriter
    3.90 +  /// \see IdMap
    3.91 +  /// \see DescriptorMap
    3.92 +  /// \see \ref GraphWriter
    3.93 +  /// \see \ref graph-io-page
    3.94 +  /// \author Balazs Dezso
    3.95 +  template <typename _Graph, typename _WriterTraits = DefaultWriterTraits> 
    3.96 +  class BpUGraphWriter {
    3.97 +  public:
    3.98 +    
    3.99 +    typedef _Graph Graph;
   3.100 +    typedef typename Graph::Node Node;
   3.101 +    typedef typename Graph::Edge Edge;
   3.102 +    typedef typename Graph::UEdge UEdge;
   3.103 +
   3.104 +    typedef _WriterTraits WriterTraits;
   3.105 +
   3.106 +    /// \brief Construct a new BpUGraphWriter.
   3.107 +    ///
   3.108 +    /// Construct a new BpUGraphWriter. It writes the given graph
   3.109 +    /// to the given stream.
   3.110 +    BpUGraphWriter(std::ostream& _os, const Graph& _graph) 
   3.111 +      : writer(new LemonWriter(_os)), own_writer(true), 
   3.112 +	nodeset_writer(*writer, _graph, std::string()),
   3.113 +	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   3.114 +	node_writer(*writer, nodeset_writer, std::string()),
   3.115 +	uedge_writer(*writer, uedgeset_writer, std::string()),
   3.116 +	attribute_writer(*writer, std::string()) {}
   3.117 +
   3.118 +    /// \brief Construct a new BpUGraphWriter.
   3.119 +    ///
   3.120 +    /// Construct a new BpUGraphWriter. It writes the given graph
   3.121 +    /// to the given file.
   3.122 +    BpUGraphWriter(const std::string& _filename, const Graph& _graph) 
   3.123 +      : writer(new LemonWriter(_filename)), own_writer(true), 
   3.124 +	nodeset_writer(*writer, _graph, std::string()),
   3.125 +	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   3.126 +	node_writer(*writer, nodeset_writer, std::string()),
   3.127 +	uedge_writer(*writer, uedgeset_writer, std::string()),
   3.128 +	attribute_writer(*writer, std::string()) {}
   3.129 +
   3.130 +    /// \brief Construct a new BpUGraphWriter.
   3.131 +    ///
   3.132 +    /// Construct a new BpUGraphWriter. It writes the given graph
   3.133 +    /// to given LemonWriter.
   3.134 +    BpUGraphWriter(LemonWriter& _writer, const Graph& _graph)
   3.135 +      : writer(_writer), own_writer(false), 
   3.136 +	nodeset_writer(*writer, _graph, std::string()),
   3.137 +	uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
   3.138 +	node_writer(*writer, nodeset_writer, std::string()),
   3.139 +	uedge_writer(*writer, uedgeset_writer, std::string()),
   3.140 +	attribute_writer(*writer, std::string()) {}
   3.141 +
   3.142 +    /// \brief Destruct the graph writer.
   3.143 +    ///
   3.144 +    /// Destruct the graph writer.
   3.145 +    ~BpUGraphWriter() {
   3.146 +      if (own_writer) 
   3.147 +	delete writer;
   3.148 +    }
   3.149 +
   3.150 +    /// \brief Issue a new node map writing command to the writer.
   3.151 +    ///
   3.152 +    /// This function issues a new <i> node map writing command</i> to
   3.153 +    /// the writer.
   3.154 +    template <typename Map>
   3.155 +    BpUGraphWriter& writeNodeMap(std::string label, const Map& map) {
   3.156 +      nodeset_writer.writeNodeMap(label, map);
   3.157 +      return *this;
   3.158 +    }
   3.159 +
   3.160 +    /// \brief Issue a new node map writing command to the writer.
   3.161 +    ///
   3.162 +    /// This function issues a new <i> node map writing command</i> to
   3.163 +    /// the writer.
   3.164 +    template <typename ItemWriter, typename Map>
   3.165 +    BpUGraphWriter& writeNodeMap(std::string label, const Map& map, 
   3.166 +			      const ItemWriter& iw = ItemWriter()) {
   3.167 +      nodeset_writer.writeNodeMap(label, map, iw);
   3.168 +      return *this;
   3.169 +    }
   3.170 +
   3.171 +    /// \brief Issue a new A-node map writing command to the writer.
   3.172 +    ///
   3.173 +    /// This function issues a new <i> A-node map writing command</i> to
   3.174 +    /// the writer.
   3.175 +    template <typename Map>
   3.176 +    BpUGraphWriter& writeANodeMap(std::string label, const Map& map) {
   3.177 +      nodeset_writer.writeANodeMap(label, map);
   3.178 +      return *this;
   3.179 +    }
   3.180 +
   3.181 +    /// \brief Issue a new A-node map writing command to the writer.
   3.182 +    ///
   3.183 +    /// This function issues a new <i> A-node map writing command</i> to
   3.184 +    /// the writer.
   3.185 +    template <typename ItemWriter, typename Map>
   3.186 +    BpUGraphWriter& writeANodeMap(std::string label, const Map& map, 
   3.187 +			      const ItemWriter& iw = ItemWriter()) {
   3.188 +      nodeset_writer.writeANodeMap(label, map, iw);
   3.189 +      return *this;
   3.190 +    }
   3.191 +    /// \brief Issue a new B-node map writing command to the writer.
   3.192 +    ///
   3.193 +    /// This function issues a new <i> B-node map writing command</i> to
   3.194 +    /// the writer.
   3.195 +    template <typename Map>
   3.196 +    BpUGraphWriter& writeBNodeMap(std::string label, const Map& map) {
   3.197 +      nodeset_writer.writeBNodeMap(label, map);
   3.198 +      return *this;
   3.199 +    }
   3.200 +
   3.201 +    /// \brief Issue a new B-node map writing command to the writer.
   3.202 +    ///
   3.203 +    /// This function issues a new <i> B-node map writing command</i> to
   3.204 +    /// the writer.
   3.205 +    template <typename ItemWriter, typename Map>
   3.206 +    BpUGraphWriter& writeBNodeMap(std::string label, const Map& map, 
   3.207 +			      const ItemWriter& iw = ItemWriter()) {
   3.208 +      nodeset_writer.writeBNodeMap(label, map, iw);
   3.209 +      return *this;
   3.210 +    }
   3.211 +
   3.212 +    /// \brief Issue a new edge map writing command to the writer.
   3.213 +    ///
   3.214 +    /// This function issues a new <i> edge map writing command</i> to
   3.215 +    /// the writer.
   3.216 +    template <typename Map>
   3.217 +    BpUGraphWriter& writeEdgeMap(std::string label, const Map& map) { 
   3.218 +      uedgeset_writer.writeEdgeMap(label, map);
   3.219 +      return *this;
   3.220 +    }
   3.221 +
   3.222 +    /// \brief Issue a new edge map writing command to the writer.
   3.223 +    ///
   3.224 +    /// This function issues a new <i> edge map writing command</i> to
   3.225 +    /// the writer.
   3.226 +    template <typename ItemWriter, typename Map>
   3.227 +    BpUGraphWriter& writeEdgeMap(std::string label, const Map& map,
   3.228 +				   const ItemWriter& iw = ItemWriter()) {
   3.229 +      uedgeset_writer.writeEdgeMap(label, map, iw);
   3.230 +      return *this;
   3.231 +    }
   3.232 +
   3.233 +    /// \brief Issue a new undirected edge map writing command to the writer.
   3.234 +    ///
   3.235 +    /// This function issues a new <i> undirected edge map writing
   3.236 +    /// command</i> to the writer.
   3.237 +    template <typename Map>
   3.238 +    BpUGraphWriter& writeUEdgeMap(std::string label, const Map& map) { 
   3.239 +      uedgeset_writer.writeUEdgeMap(label, map);
   3.240 +      return *this;
   3.241 +    }
   3.242 +
   3.243 +    /// \brief Issue a new undirected edge map writing command to the writer.
   3.244 +    ///
   3.245 +    /// This function issues a new <i> undirected edge map writing
   3.246 +    /// command</i> to the writer.
   3.247 +   template <typename ItemWriter, typename Map>
   3.248 +    BpUGraphWriter& writeUEdgeMap(std::string label, const Map& map,
   3.249 +					const ItemWriter& iw = ItemWriter()) {
   3.250 +      uedgeset_writer.writeUEdgeMap(label, map, iw);
   3.251 +      return *this;
   3.252 +    }
   3.253 +
   3.254 +    /// \brief Issue a new labeled node writer to the writer.
   3.255 +    ///
   3.256 +    /// This function issues a new <i> labeled node writing
   3.257 +    /// command</i> to the writer.
   3.258 +    BpUGraphWriter& writeNode(std::string label, const Node& node) {
   3.259 +      node_writer.writeNode(label, node);
   3.260 +      return *this;
   3.261 +    }
   3.262 +
   3.263 +    /// \brief Issue a new labeled edge writer to the writer.
   3.264 +    ///
   3.265 +    /// This function issues a new <i> labeled edge writing
   3.266 +    /// command</i> to the writer.
   3.267 +    BpUGraphWriter& writeEdge(std::string label, const Edge& edge) {
   3.268 +      uedge_writer.writeEdge(label, edge);
   3.269 +    }
   3.270 +
   3.271 +    /// \brief Issue a new labeled undirected edge writing command to
   3.272 +    /// the writer.
   3.273 +    ///
   3.274 +    /// Issue a new <i>labeled undirected edge writing command</i> to
   3.275 +    /// the writer.
   3.276 +    BpUGraphWriter& writeUEdge(std::string label, const UEdge& edge) {
   3.277 +      uedge_writer.writeUEdge(label, edge);
   3.278 +    }
   3.279 +
   3.280 +    /// \brief Issue a new attribute writing command.
   3.281 +    ///
   3.282 +    /// This function issues a new <i> attribute writing
   3.283 +    /// command</i> to the writer.
   3.284 +    template <typename Value>
   3.285 +    BpUGraphWriter& writeAttribute(std::string label, const Value& value) {
   3.286 +      attribute_writer.writeAttribute(label, value);
   3.287 +      return *this;
   3.288 +    }
   3.289 +    
   3.290 +    /// \brief Issue a new attribute writing command.
   3.291 +    ///
   3.292 +    /// This function issues a new <i> attribute writing
   3.293 +    /// command</i> to the writer.
   3.294 +    template <typename ItemWriter, typename Value>
   3.295 +    BpUGraphWriter& writeAttribute(std::string label, const Value& value, 
   3.296 +			       const ItemWriter& iw = ItemWriter()) {
   3.297 +      attribute_writer.writeAttribute(label, value, iw);
   3.298 +      return *this;
   3.299 +    }
   3.300 +
   3.301 +    /// \brief Conversion operator to LemonWriter.
   3.302 +    ///
   3.303 +    /// Conversion operator to LemonWriter. It makes possible
   3.304 +    /// to access the encapsulated \e LemonWriter, this way
   3.305 +    /// you can attach to this writer new instances of 
   3.306 +    /// \e LemonWriter::SectionWriter.
   3.307 +    operator LemonWriter&() {
   3.308 +      return *writer;
   3.309 +    }
   3.310 +
   3.311 +    /// \brief Executes the writing commands.
   3.312 +    ///
   3.313 +    /// Executes the writing commands.
   3.314 +    void run() {
   3.315 +      writer->run();
   3.316 +    }
   3.317 +
   3.318 +    /// \brief Returns true if the writer can give back the labels by the items.
   3.319 +    ///
   3.320 +    /// Returns true if the writer can give back the the labels by the items.
   3.321 +    bool isLabelWriter() const {
   3.322 +      return nodeset_writer.isLabelWriter() && 
   3.323 +        uedgeset_writer.isLabelWriter();
   3.324 +    }
   3.325 +
   3.326 +    /// \brief Write the label of the given node.
   3.327 +    ///
   3.328 +    /// It writes the label of the given node. If there was written a "label"
   3.329 +    /// named node map then it will write the map value belonging to the node.
   3.330 +    void writeLabel(std::ostream& os, const Node& item) const {
   3.331 +      nodeset_writer.writeLabel(os, item);
   3.332 +    } 
   3.333 +
   3.334 +    /// \brief Write the label of the given edge.
   3.335 +    ///
   3.336 +    /// It writes the label of the given edge. If there was written a "label"
   3.337 +    /// named edge map then it will write the map value belonging to the edge.
   3.338 +    void writeLabel(std::ostream& os, const Edge& item) const {
   3.339 +      uedgeset_writer.writeLabel(os, item);
   3.340 +    } 
   3.341 +
   3.342 +    /// \brief Write the label of the given undirected edge.
   3.343 +    ///
   3.344 +    /// It writes the label of the given undirected edge. If there was
   3.345 +    /// written a "label" named edge map then it will write the map
   3.346 +    /// value belonging to the edge.
   3.347 +    void writeLabel(std::ostream& os, const UEdge& item) const {
   3.348 +      uedgeset_writer.writeLabel(os, item);
   3.349 +    } 
   3.350 +
   3.351 +    /// \brief Sorts the given node vector by label.
   3.352 +    ///
   3.353 +    /// Sorts the given node vector by label. If there was written an
   3.354 +    /// "label" named map then the vector will be sorted by the values
   3.355 +    /// of this map. Otherwise if the \c forceLabel parameter was true
   3.356 +    /// it will be sorted by its id in the graph.
   3.357 +    void sortByLabel(std::vector<Node>& nodes) const {
   3.358 +      nodeset_writer.sortByLabel(nodes);
   3.359 +    }
   3.360 +
   3.361 +    /// \brief Sorts the given edge vector by label.
   3.362 +    ///
   3.363 +    /// Sorts the given edge vector by label. If there was written an
   3.364 +    /// "label" named map then the vector will be sorted by the values
   3.365 +    /// of this map. Otherwise if the \c forceLabel parameter was true
   3.366 +    /// it will be sorted by its id in the graph.
   3.367 +    void sortByLabel(std::vector<Edge>& edges) const {
   3.368 +      uedgeset_writer.sortByLabel(edges);
   3.369 +    }
   3.370 +
   3.371 +    /// \brief Sorts the given undirected edge vector by label.
   3.372 +    ///
   3.373 +    /// Sorts the given undirected edge vector by label. If there was
   3.374 +    /// written an "label" named map then the vector will be sorted by
   3.375 +    /// the values of this map. Otherwise if the \c forceLabel
   3.376 +    /// parameter was true it will be sorted by its id in the graph.
   3.377 +    void sortByLabel(std::vector<UEdge>& uedges) const {
   3.378 +      uedgeset_writer.sortByLabel(uedges);
   3.379 +    }
   3.380 +
   3.381 +  private:
   3.382 +
   3.383 +    LemonWriter* writer;
   3.384 +    bool own_writer;
   3.385 +
   3.386 +    BpNodeSetWriter<Graph, WriterTraits> nodeset_writer;
   3.387 +    UEdgeSetWriter<Graph, WriterTraits> uedgeset_writer;
   3.388 +
   3.389 +    NodeWriter<Graph> node_writer;
   3.390 +    UEdgeWriter<Graph> uedge_writer;
   3.391 +    
   3.392 +    AttributeWriter<WriterTraits> attribute_writer;
   3.393 +  };
   3.394 +
   3.395    /// @}
   3.396  
   3.397  }
     4.1 --- a/lemon/lemon_reader.h	Sat Oct 20 14:29:12 2007 +0000
     4.2 +++ b/lemon/lemon_reader.h	Wed Oct 24 16:31:49 2007 +0000
     4.3 @@ -311,7 +311,7 @@
     4.4  
     4.5        MapReaderBase() { _touched = false; }
     4.6        
     4.7 -      void touch() { _touched = true; }
     4.8 +      void touch(bool value = true) { _touched = value; }
     4.9        bool touched() const { return _touched; }
    4.10  
    4.11        virtual ~MapReaderBase() {}
    4.12 @@ -593,8 +593,7 @@
    4.13  
    4.14        virtual int_type underflow() {
    4.15  	char c;
    4.16 -	if (_is.read(&c, 1)) {
    4.17 -	  _is.putback(c);
    4.18 +	if ((c = _is.peek()) != EOF) {
    4.19  	  if (c == '@') {
    4.20  	    return EOF;
    4.21  	  }
    4.22 @@ -603,13 +602,13 @@
    4.23  	}
    4.24  	char_type *ptr;
    4.25  	for (ptr = base(); ptr != eptr(); ++ptr) {
    4.26 -	  if (_is.read(&c, 1)) {
    4.27 +	  if ((c = _is.get()) != EOF) {
    4.28  	    if (c == '\n') ++_num;
    4.29  	    if (put_char(c)) {
    4.30  	      *ptr = c;
    4.31  	    } else {
    4.32  	      if (skip_state == after_endl && c == '@') {
    4.33 -		_is.putback('@');
    4.34 +		_is.putback(c);
    4.35  		break;
    4.36  	      }
    4.37  	      --ptr;
    4.38 @@ -638,6 +637,36 @@
    4.39  
    4.40      };
    4.41  
    4.42 +    static void skipPreSection(std::istream& is, int& line_num) {
    4.43 +      enum skip_state_type { skip, after_endl };
    4.44 +
    4.45 +      skip_state_type skip_state = after_endl;
    4.46 +      char c;
    4.47 +      
    4.48 +      while ((c = is.get()) != EOF) {
    4.49 +	if (c == '\n') ++line_num;
    4.50 +
    4.51 +	switch (skip_state) {
    4.52 +	case skip:
    4.53 +	  if (c == '\n') skip_state = after_endl;
    4.54 +	  break;
    4.55 +	case after_endl:
    4.56 +	  switch (c) {
    4.57 +	  case '@':
    4.58 +	    is.putback(c);
    4.59 +	    return;
    4.60 +	  case '\n':
    4.61 +	    continue;
    4.62 +	  default:
    4.63 +	    if (!isspace(c)) {
    4.64 +	      skip_state = skip;
    4.65 +	    }
    4.66 +	    break;
    4.67 +	  }
    4.68 +	}	
    4.69 +      }
    4.70 +    }
    4.71 +
    4.72    public:
    4.73  
    4.74      /// \brief Abstract base class for reading a section.
    4.75 @@ -722,6 +751,7 @@
    4.76        std::string line;
    4.77        
    4.78        SectionReaders::iterator it;
    4.79 +      skipPreSection(*is, line_num);
    4.80        while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
    4.81  	for (it = readers.begin(); it != readers.end(); ++it) {
    4.82  	  if (it->first->header(line)) {
    4.83 @@ -732,6 +762,7 @@
    4.84  	      buffer.pubsetbuf(buf, sizeof(buf));
    4.85  	      std::istream ss(&buffer);
    4.86  	      it->first->read(ss);
    4.87 +	      skipPreSection(*is, line_num);
    4.88  	      break;
    4.89  	    } catch (DataFormatError& error) {
    4.90  	      error.line(buffer.line_num());
    4.91 @@ -984,6 +1015,465 @@
    4.92    };
    4.93  
    4.94    /// \ingroup section_io
    4.95 +  /// \brief SectionReader for reading a bipartite graph's nodeset.
    4.96 +  ///
    4.97 +  /// The lemon format can store multiple bipartite graph nodesets
    4.98 +  /// with several maps. The bipartite graph nodeset section's header
    4.99 +  /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
   4.100 +  /// may be empty.
   4.101 +  ///
   4.102 +  /// The first line of the section contains \c "&anodeset" and the
   4.103 +  /// the names of the A-node maps and regular maps separated with
   4.104 +  /// white spaces. Each next lines describes an A-node in the anodeset,
   4.105 +  /// and contains the mapped values for each map. If one of the line
   4.106 +  /// starts with \c "&bnodeset" then this line contains the names of
   4.107 +  /// the B-node maps and the regular node maps. And the remaining lines
   4.108 +  /// contains the mapped values to the B-nodes.
   4.109 +  ///
   4.110 +  /// If there is "label" named map then it should be defined in both
   4.111 +  /// nodeset, and it will be regarded as id map. This map should
   4.112 +  /// contain only unique values and when the \c readLabel() member
   4.113 +  /// will read a value from the given stream it will give back that
   4.114 +  /// node which is mapped to this value.
   4.115 +  ///
   4.116 +  /// \relates LemonReader
   4.117 +  template <typename _Graph, typename _Traits = DefaultReaderTraits>
   4.118 +  class BpNodeSetReader : public LemonReader::SectionReader {
   4.119 +    typedef LemonReader::SectionReader Parent;
   4.120 +  public:
   4.121 +
   4.122 +    typedef _Graph Graph;
   4.123 +    typedef _Traits Traits;
   4.124 +    typedef typename Graph::Node Node;
   4.125 +    typedef typename Traits::Skipper DefaultSkipper;
   4.126 +
   4.127 +    /// \brief Constructor.
   4.128 +    ///
   4.129 +    /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
   4.130 +    /// attach it into the given LemonReader. The nodeset reader will
   4.131 +    /// add the read nodes to the given Graph. The reader will read
   4.132 +    /// the section when the \c section_name and the \c _name are the same. 
   4.133 +    BpNodeSetReader(LemonReader& _reader, 
   4.134 +		  Graph& _graph, 
   4.135 +		  const std::string& _name = std::string(),
   4.136 +		  const DefaultSkipper& _skipper = DefaultSkipper()) 
   4.137 +      : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} 
   4.138 +
   4.139 +
   4.140 +    /// \brief Destructor.
   4.141 +    ///
   4.142 +    /// Destructor for BpNodeSetReader.
   4.143 +    virtual ~BpNodeSetReader() {
   4.144 +      for (typename MapReaders::iterator it = readers.begin(); 
   4.145 +	   it != readers.end(); ++it) {
   4.146 +	delete it->second;
   4.147 +      }
   4.148 +    }
   4.149 +
   4.150 +  private:
   4.151 +    BpNodeSetReader(const BpNodeSetReader&);
   4.152 +    void operator=(const BpNodeSetReader&);
   4.153 +  
   4.154 +  public:
   4.155 +
   4.156 +    /// \brief Add a new node map reader command for the reader.
   4.157 +    ///
   4.158 +    /// Add a new node map reader command for the reader.
   4.159 +    template <typename Map>
   4.160 +    BpNodeSetReader& readNodeMap(std::string label, Map& map) {
   4.161 +      return _readMap<
   4.162 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.163 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.164 +    }
   4.165 +
   4.166 +    template <typename Map>
   4.167 +    BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
   4.168 +      return _readMap<
   4.169 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.170 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.171 +    }
   4.172 +
   4.173 +    /// \brief Add a new node map reader command for the reader.
   4.174 +    ///
   4.175 +    /// Add a new node map reader command for the reader.
   4.176 +    template <typename ItemReader, typename Map>
   4.177 +    BpNodeSetReader& readNodeMap(std::string label, Map& map, 
   4.178 +			       const ItemReader& ir = ItemReader()) {
   4.179 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.180 +	(label, map, ir);
   4.181 +    }
   4.182 +
   4.183 +    template <typename ItemReader, typename Map>
   4.184 +    BpNodeSetReader& readNodeMap(std::string label, const Map& map, 
   4.185 +			       const ItemReader& ir = ItemReader()) {
   4.186 +      return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.187 +	(label, map, ir);
   4.188 +    }
   4.189 +
   4.190 +  private:
   4.191 +
   4.192 +    template <typename ItemReader, typename Map, typename MapParameter>
   4.193 +    BpNodeSetReader& _readMap(std::string label, MapParameter map, 
   4.194 +			    const ItemReader& ir = ItemReader()) {
   4.195 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   4.196 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   4.197 +      if (areaders.find(label) != areaders.end() ||
   4.198 +	  breaders.find(label) != breaders.end() ||
   4.199 +	  readers.find(label) != readers.end()) {
   4.200 +	ErrorMessage msg;
   4.201 +	msg << "Multiple read rule for node map: " << label;
   4.202 +	throw IoParameterError(msg.message());
   4.203 +      }      
   4.204 +      readers.insert(make_pair(label, new _reader_bits::
   4.205 +		  MapReader<Node, Map, ItemReader>(map, ir)));
   4.206 +      return *this;
   4.207 +    }
   4.208 +
   4.209 +  public:
   4.210 +
   4.211 +    /// \brief Add a new A-node map reader command for the reader.
   4.212 +    ///
   4.213 +    /// Add a new A-node map reader command for the reader.
   4.214 +    template <typename Map>
   4.215 +    BpNodeSetReader& readANodeMap(std::string label, Map& map) {
   4.216 +      return _readAMap<
   4.217 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.218 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.219 +    }
   4.220 +
   4.221 +    template <typename Map>
   4.222 +    BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
   4.223 +      return _readAMap<
   4.224 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.225 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.226 +    }
   4.227 +
   4.228 +    /// \brief Add a new A-node map reader command for the reader.
   4.229 +    ///
   4.230 +    /// Add a new A-node map reader command for the reader.
   4.231 +    template <typename ItemReader, typename Map>
   4.232 +    BpNodeSetReader& readANodeMap(std::string label, Map& map, 
   4.233 +			       const ItemReader& ir = ItemReader()) {
   4.234 +      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.235 +	(label, map, ir);
   4.236 +    }
   4.237 +
   4.238 +    template <typename ItemReader, typename Map>
   4.239 +    BpNodeSetReader& readANodeMap(std::string label, const Map& map, 
   4.240 +			       const ItemReader& ir = ItemReader()) {
   4.241 +      return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.242 +	(label, map, ir);
   4.243 +    }
   4.244 +
   4.245 +  private:
   4.246 +
   4.247 +    template <typename ItemReader, typename Map, typename MapParameter>
   4.248 +    BpNodeSetReader& _readAMap(std::string label, MapParameter map, 
   4.249 +			    const ItemReader& ir = ItemReader()) {
   4.250 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   4.251 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   4.252 +      if (label == "label") {
   4.253 +	throw IoParameterError("Label cannot be A-node map");
   4.254 +      }
   4.255 +      if (areaders.find(label) != areaders.end() ||
   4.256 +	  readers.find(label) != readers.end()) {
   4.257 +	ErrorMessage msg;
   4.258 +	msg << "Multiple read rule for A-node map: " << label;
   4.259 +	throw IoParameterError(msg.message());
   4.260 +      }
   4.261 +      areaders.insert(make_pair(label, new _reader_bits::
   4.262 +				MapReader<Node, Map, ItemReader>(map, ir)));
   4.263 +      return *this;
   4.264 +    }
   4.265 +
   4.266 +  public:
   4.267 +
   4.268 +    /// \brief Add a new B-node map reader command for the reader.
   4.269 +    ///
   4.270 +    /// Add a new B-node map reader command for the reader.
   4.271 +    template <typename Map>
   4.272 +    BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
   4.273 +      return _readBMap<
   4.274 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.275 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.276 +    }
   4.277 +
   4.278 +    template <typename Map>
   4.279 +    BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
   4.280 +      return _readBMap<
   4.281 +	typename Traits::template Reader<typename Map::Value>, Map,
   4.282 +	typename _reader_bits::Arg<Map>::Type>(label, map);
   4.283 +    }
   4.284 +
   4.285 +    /// \brief Add a new B-node map reader command for the reader.
   4.286 +    ///
   4.287 +    /// Add a new B-node map reader command for the reader.
   4.288 +    template <typename ItemReader, typename Map>
   4.289 +    BpNodeSetReader& readBNodeMap(std::string label, Map& map, 
   4.290 +			       const ItemReader& ir = ItemReader()) {
   4.291 +      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.292 +	(label, map, ir);
   4.293 +    }
   4.294 +
   4.295 +    template <typename ItemReader, typename Map>
   4.296 +    BpNodeSetReader& readBNodeMap(std::string label, const Map& map, 
   4.297 +			       const ItemReader& ir = ItemReader()) {
   4.298 +      return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
   4.299 +	(label, map, ir);
   4.300 +    }
   4.301 +
   4.302 +  private:
   4.303 +
   4.304 +    template <typename ItemReader, typename Map, typename MapParameter>
   4.305 +    BpNodeSetReader& _readBMap(std::string label, MapParameter map, 
   4.306 +			    const ItemReader& ir = ItemReader()) {
   4.307 +      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
   4.308 +      checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
   4.309 +      if (label == "label") {
   4.310 +	throw IoParameterError("Label cannot be B-node map");
   4.311 +      }
   4.312 +      if (breaders.find(label) != breaders.end() ||
   4.313 +	  readers.find(label) != readers.end()) {
   4.314 +	ErrorMessage msg;
   4.315 +	msg << "Multiple read rule for B-node map: " << label;
   4.316 +	throw IoParameterError(msg.message());
   4.317 +      }
   4.318 +      breaders.insert(make_pair(label, new _reader_bits::
   4.319 +				MapReader<Node, Map, ItemReader>(map, ir)));
   4.320 +      return *this;
   4.321 +    }
   4.322 +
   4.323 +  public:
   4.324 +
   4.325 +    /// \brief Add a new node map skipper command for the reader.
   4.326 +    ///
   4.327 +    /// Add a new node map skipper command for the reader.
   4.328 +    template <typename ItemReader>
   4.329 +    BpNodeSetReader& skipNodeMap(std::string label, 
   4.330 +				 const ItemReader& ir = ItemReader()) {
   4.331 +      if (areaders.find(label) != areaders.end() ||
   4.332 +	  breaders.find(label) != breaders.end() ||
   4.333 +	  readers.find(label) != readers.end()) {
   4.334 +	ErrorMessage msg;
   4.335 +	msg << "Multiple read rule for node map: " << label;
   4.336 +	throw IoParameterError(msg.message());
   4.337 +      }
   4.338 +      readers.insert(make_pair(label, new _reader_bits::
   4.339 +			       SkipReader<Node, ItemReader>(ir)));
   4.340 +      return *this;
   4.341 +    }
   4.342 +
   4.343 +    /// \brief Add a new A-node map skipper command for the reader.
   4.344 +    ///
   4.345 +    /// Add a new A-node map skipper command for the reader.
   4.346 +    template <typename ItemReader>
   4.347 +    BpNodeSetReader& skipANodeMap(std::string label, 
   4.348 +				  const ItemReader& ir = ItemReader()) {
   4.349 +      if (label == "label") {
   4.350 +	throw IoParameterError("Label cannot be A-node map");
   4.351 +      }
   4.352 +      if (areaders.find(label) != areaders.end() ||
   4.353 +	  readers.find(label) != readers.end()) {
   4.354 +	ErrorMessage msg;
   4.355 +	msg << "Multiple read rule for A-node map: " << label;
   4.356 +	throw IoParameterError(msg.message());
   4.357 +      }
   4.358 +      areaders.insert(make_pair(label, new _reader_bits::
   4.359 +				SkipReader<Node, ItemReader>(ir)));
   4.360 +      return *this;
   4.361 +    }
   4.362 +
   4.363 +    /// \brief Add a new B-node map skipper command for the reader.
   4.364 +    ///
   4.365 +    /// Add a new B-node map skipper command for the reader.
   4.366 +    template <typename ItemReader>
   4.367 +    BpNodeSetReader& skipBNodeMap(std::string label, 
   4.368 +				  const ItemReader& ir = ItemReader()) {
   4.369 +      if (label == "label") {
   4.370 +	throw IoParameterError("Label cannot be B-node map");
   4.371 +      }
   4.372 +      if (breaders.find(label) != breaders.end() ||
   4.373 +	  readers.find(label) != readers.end()) {
   4.374 +	ErrorMessage msg;
   4.375 +	msg << "Multiple read rule for B-node map: " << label;
   4.376 +	throw IoParameterError(msg.message());
   4.377 +      }
   4.378 +      breaders.insert(make_pair(label, new _reader_bits::
   4.379 +				SkipReader<Node, ItemReader>(ir)));
   4.380 +      return *this;
   4.381 +    }
   4.382 +
   4.383 +
   4.384 +  protected:
   4.385 +
   4.386 +    /// \brief Gives back true when the SectionReader can process 
   4.387 +    /// the section with the given header line.
   4.388 +    ///
   4.389 +    /// It gives back true when the header line starts with \c \@nodeset,
   4.390 +    /// and the header line's name and the nodeset's name are the same.
   4.391 +    virtual bool header(const std::string& line) {
   4.392 +      std::istringstream ls(line);
   4.393 +      std::string command;
   4.394 +      std::string id;
   4.395 +      ls >> command >> id;
   4.396 +      return command == "@bpnodeset" && name == id;
   4.397 +    }
   4.398 +
   4.399 +    /// \brief Reader function of the section.
   4.400 +    ///
   4.401 +    /// It reads the content of the section.
   4.402 +    virtual void read(std::istream& is) {
   4.403 +      std::string line;
   4.404 +      {
   4.405 +	std::vector<_reader_bits::MapReaderBase<Node>* > index;
   4.406 +	{
   4.407 +	  getline(is, line);
   4.408 +	  std::istringstream ls(line);
   4.409 +	  std::string id;
   4.410 +	  ls >> id;
   4.411 +	  if (id != "&anodeset") {
   4.412 +	    throw IoParameterError("Cannot find &anodeset subsection");
   4.413 +	  }
   4.414 +	  while (ls >> id) {
   4.415 +	    typename MapReaders::iterator it = readers.find(id);
   4.416 +	    typename MapReaders::iterator ait = areaders.find(id);
   4.417 +	    if (it != readers.end()) {
   4.418 +	      it->second->touch();
   4.419 +	      index.push_back(it->second);
   4.420 +	    } else if (ait != areaders.end()) {
   4.421 +	      ait->second->touch();
   4.422 +	      index.push_back(ait->second);
   4.423 +	    }
   4.424 +	    if (id == "label") {
   4.425 +	      inverter.reset(index.back()->getInverter());
   4.426 +	      index.back() = inverter.get();
   4.427 +	    }
   4.428 +	  }
   4.429 +	}
   4.430 +	for (typename MapReaders::iterator it = areaders.begin();
   4.431 +	     it != areaders.end(); ++it) {
   4.432 +	  if (!it->second->touched()) {
   4.433 +	    ErrorMessage msg;
   4.434 +	    msg << "Map not found in file: " << it->first;
   4.435 +	    throw IoParameterError(msg.message());
   4.436 +	  }
   4.437 +	}
   4.438 +	for (typename MapReaders::iterator it = readers.begin();
   4.439 +	     it != readers.end(); ++it) {
   4.440 +	  if (!it->second->touched()) {
   4.441 +	    ErrorMessage msg;
   4.442 +	    msg << "Map not found in file: " << it->first;
   4.443 +	    throw IoParameterError(msg.message());
   4.444 +	  }
   4.445 +	  it->second->touch(false);
   4.446 +	}
   4.447 +
   4.448 +	while (getline(is, line)) {
   4.449 +	  if (line[0] == '&') {
   4.450 +	    std::istringstream ls(line);
   4.451 +	    std::string id;
   4.452 +	    ls >> id;
   4.453 +	    if (id == "&bnodeset") break;
   4.454 +	  }
   4.455 +	  Node node = graph.addANode();
   4.456 +	  std::istringstream ls(line);
   4.457 +	  for (int i = 0; i < int(index.size()); ++i) {
   4.458 +	    index[i]->read(ls, node);
   4.459 +	  }
   4.460 +	}
   4.461 +      }
   4.462 +
   4.463 +      {
   4.464 +	std::vector<_reader_bits::MapReaderBase<Node>* > index;
   4.465 +	{
   4.466 +	  std::istringstream ls(line);
   4.467 +	  std::string id;
   4.468 +	  ls >> id;
   4.469 +	  if (id != "&bnodeset") {
   4.470 +	    throw IoParameterError("Cannot find &bnodeset subsection");
   4.471 +	  }
   4.472 +	  while (ls >> id) {
   4.473 +	    typename MapReaders::iterator it = readers.find(id);
   4.474 +	    typename MapReaders::iterator bit = breaders.find(id);
   4.475 +	    if (it != readers.end()) {
   4.476 +	      it->second->touch();
   4.477 +	      index.push_back(it->second);
   4.478 +	    } else if (bit != breaders.end()) {
   4.479 +	      bit->second->touch();
   4.480 +	      index.push_back(bit->second);
   4.481 +	    }
   4.482 +	    if (id == "label" && inverter.get() != 0) {
   4.483 +	      index.back() = inverter.get();
   4.484 +	    }
   4.485 +	  }
   4.486 +	}
   4.487 +	for (typename MapReaders::iterator it = breaders.begin();
   4.488 +	     it != breaders.end(); ++it) {
   4.489 +	  if (!it->second->touched()) {
   4.490 +	    ErrorMessage msg;
   4.491 +	    msg << "Map not found in file: " << it->first;
   4.492 +	    throw IoParameterError(msg.message());
   4.493 +	  }
   4.494 +	}
   4.495 +	for (typename MapReaders::iterator it = readers.begin();
   4.496 +	     it != readers.end(); ++it) {
   4.497 +	  if (!it->second->touched()) {
   4.498 +	    ErrorMessage msg;
   4.499 +	    msg << "Map not found in file: " << it->first;
   4.500 +	    throw IoParameterError(msg.message());
   4.501 +	  }
   4.502 +	}
   4.503 +	while (getline(is, line)) {	
   4.504 +	  Node node = graph.addBNode();
   4.505 +	  std::istringstream ls(line);
   4.506 +	  for (int i = 0; i < int(index.size()); ++i) {
   4.507 +	    index[i]->read(ls, node);
   4.508 +	  }
   4.509 +	}
   4.510 +      }
   4.511 +    }
   4.512 +
   4.513 +    virtual void missing() {
   4.514 +      if (readers.empty()) return;
   4.515 +      ErrorMessage msg;
   4.516 +      msg << "BpNodeSet section not found in file: @bpnodeset " << name;
   4.517 +      throw IoParameterError(msg.message());
   4.518 +    }
   4.519 +
   4.520 +  public:
   4.521 +
   4.522 +    /// \brief Returns true if the nodeset can give back the node by its label.
   4.523 +    ///
   4.524 +    /// Returns true if the nodeset can give back the node by its label.
   4.525 +    /// It is possible only if an "label" named map was read.
   4.526 +    bool isLabelReader() const {
   4.527 +      return inverter.get() != 0;
   4.528 +    }
   4.529 +
   4.530 +    /// \brief Gives back the node by its label.
   4.531 +    ///
   4.532 +    /// It reads an id from the stream and gives back which node belongs to
   4.533 +    /// it. It is possible only if there was read an "label" named map.
   4.534 +    void readLabel(std::istream& is, Node& node) const {
   4.535 +      node = inverter->read(is);
   4.536 +    } 
   4.537 +
   4.538 +  private:
   4.539 +
   4.540 +    typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> 
   4.541 +    MapReaders;
   4.542 +    
   4.543 +    MapReaders areaders, breaders, readers;
   4.544 +   
   4.545 +    Graph& graph;
   4.546 +    std::string name;
   4.547 +    _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
   4.548 +
   4.549 +    std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
   4.550 +  };
   4.551 +
   4.552 +
   4.553 +  /// \ingroup section_io
   4.554    /// \brief SectionReader for reading a graph's edgeset.
   4.555    ///
   4.556    /// The lemon format can store multiple graph edgesets with several maps.
     5.1 --- a/lemon/lemon_writer.h	Sat Oct 20 14:29:12 2007 +0000
     5.2 +++ b/lemon/lemon_writer.h	Wed Oct 24 16:31:49 2007 +0000
     5.3 @@ -144,8 +144,8 @@
     5.4        }
     5.5  
     5.6      private:
     5.7 +      const Graph& graph;
     5.8        typename Ref<Map>::Type map;
     5.9 -      const Graph& graph;
    5.10      };
    5.11  
    5.12      template <typename Graph, typename Map>
    5.13 @@ -168,8 +168,8 @@
    5.14        }
    5.15  
    5.16      private:
    5.17 +      const Graph& graph;
    5.18        typename Ref<Map>::Type map;
    5.19 -      const Graph& graph;
    5.20      };
    5.21  
    5.22      template <typename Graph, typename Map>
    5.23 @@ -502,7 +502,7 @@
    5.24    /// \c writeLabel() member will be called with a node it will write it's 
    5.25    /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
    5.26    /// then the label map will be the id in the graph. In addition if the
    5.27 -  /// the \c _forceSort is true then the writer will write the edges
    5.28 +  /// the \c _forceSort is true then the writer will write the nodes
    5.29    /// sorted by the labels.
    5.30    ///
    5.31    /// \relates LemonWriter
    5.32 @@ -680,6 +680,300 @@
    5.33    };
    5.34  
    5.35    /// \ingroup section_io
    5.36 +  /// \brief SectionWriter for writing a bipartite graph's nodeset.
    5.37 +  ///
    5.38 +  /// The lemon format can store multiple bipartite graph nodesets
    5.39 +  /// with several maps.  The nodeset section's header line is \c
    5.40 +  /// \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name may be empty.
    5.41 +  ///
    5.42 +  /// The first line of the section contains the names of the maps separated
    5.43 +  /// with white spaces. Each next lines describes a node in the nodeset, and
    5.44 +  /// contains the mapped values for each map.
    5.45 +  ///
    5.46 +  /// If the nodeset contains an \c "label" named map then it will be regarded
    5.47 +  /// as label map. This map should contain only unique values and when the 
    5.48 +  /// \c writeLabel() member will be called with a node it will write it's 
    5.49 +  /// label. Otherwise if the \c _forceLabelMap constructor parameter is true 
    5.50 +  /// then the label map will be the id in the graph. In addition if the
    5.51 +  /// the \c _forceSort is true then the writer will write the edges
    5.52 +  /// sorted by the labels.
    5.53 +  ///
    5.54 +  /// \relates LemonWriter
    5.55 +  template <typename _Graph, typename _Traits = DefaultWriterTraits>
    5.56 +  class BpNodeSetWriter : public LemonWriter::SectionWriter {
    5.57 +    typedef LemonWriter::SectionWriter Parent;
    5.58 +  public:
    5.59 +
    5.60 +    typedef _Graph Graph;
    5.61 +    typedef _Traits Traits;
    5.62 +    typedef typename Graph::Node Node;
    5.63 +
    5.64 +    /// \brief Constructor.
    5.65 +    ///
    5.66 +    /// Constructor for BpNodeSetWriter. It creates the BpNodeSetWriter and
    5.67 +    /// attach it into the given LemonWriter. If the \c _forceLabelMap
    5.68 +    /// parameter is true then the writer will write own label map when
    5.69 +    /// the user does not give "label" named map. In addition if the
    5.70 +    /// the \c _forceSort is true then the writer will write the nodes
    5.71 +    /// sorted by the labels.
    5.72 +    BpNodeSetWriter(LemonWriter& _writer, const Graph& _graph, 
    5.73 +		  const std::string& _name = std::string(), 
    5.74 +		  bool _forceLabelMap = true, bool _forceSort = true) 
    5.75 +      : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), 
    5.76 +	forceSort(_forceSort), graph(_graph), name(_name) {}
    5.77 +
    5.78 +    /// \brief Destructor.
    5.79 +    ///
    5.80 +    /// Destructor for BpNodeSetWriter.
    5.81 +    virtual ~BpNodeSetWriter() {
    5.82 +      typename MapWriters::iterator it;
    5.83 +      for (it = writers.begin(); it != writers.end(); ++it) {
    5.84 +	delete it->second;
    5.85 +      }
    5.86 +    }
    5.87 +
    5.88 +  private:
    5.89 +    BpNodeSetWriter(const BpNodeSetWriter&);
    5.90 +    void operator=(const BpNodeSetWriter&);
    5.91 +  
    5.92 +  public:
    5.93 +
    5.94 +    /// \brief Add a new A-node map writer command for the writer.
    5.95 +    ///
    5.96 +    /// Add a new A-node map writer command for the writer.
    5.97 +    template <typename Map>
    5.98 +    BpNodeSetWriter& writeANodeMap(std::string label, const Map& map) {
    5.99 +      return writeANodeMap<typename Traits::
   5.100 +	template Writer<typename Map::Value>, Map>(label, map);
   5.101 +    }
   5.102 +
   5.103 +    /// \brief Add a new A-node map writer command for the writer.
   5.104 +    ///
   5.105 +    /// Add a new A-node map writer command for the writer.
   5.106 +    template <typename ItemWriter, typename Map>
   5.107 +    BpNodeSetWriter& writeANodeMap(std::string label, const Map& map, 
   5.108 +				   const ItemWriter& iw = ItemWriter()) {
   5.109 +      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   5.110 +      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
   5.111 +      if (label == "label") {
   5.112 +	throw IoParameterError("Label cannot be A-node map");
   5.113 +      }
   5.114 +      awriters.push_back(make_pair(label, new _writer_bits::
   5.115 +				   MapWriter<Node, Map, ItemWriter>(map, iw)));
   5.116 +      return *this;
   5.117 +    }
   5.118 +
   5.119 +    /// \brief Add a new B-node map writer command for the writer.
   5.120 +    ///
   5.121 +    /// Add a new B-node map writer command for the writer.
   5.122 +    template <typename Map>
   5.123 +    BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map) {
   5.124 +      return writeBNodeMap<typename Traits::
   5.125 +	template Writer<typename Map::Value>, Map>(label, map);
   5.126 +    }
   5.127 +
   5.128 +    /// \brief Add a new B-node map writer command for the writer.
   5.129 +    ///
   5.130 +    /// Add a new B-node map writer command for the writer.
   5.131 +    template <typename ItemWriter, typename Map>
   5.132 +    BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map, 
   5.133 +				   const ItemWriter& iw = ItemWriter()) {
   5.134 +      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   5.135 +      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
   5.136 +      if (label == "label") {
   5.137 +	throw IoParameterError("Label cannot be B-node map");
   5.138 +      }
   5.139 +      bwriters.push_back(make_pair(label, new _writer_bits::
   5.140 +				   MapWriter<Node, Map, ItemWriter>(map, iw)));
   5.141 +      return *this;
   5.142 +    }
   5.143 +
   5.144 +    /// \brief Add a new node map writer command for the writer.
   5.145 +    ///
   5.146 +    /// Add a new node map writer command for the writer.
   5.147 +    template <typename Map>
   5.148 +    BpNodeSetWriter& writeNodeMap(std::string label, const Map& map) {
   5.149 +      return writeNodeMap<typename Traits::
   5.150 +	template Writer<typename Map::Value>, Map>(label, map);
   5.151 +    }
   5.152 +
   5.153 +    /// \brief Add a new node map writer command for the writer.
   5.154 +    ///
   5.155 +    /// Add a new node map writer command for the writer.
   5.156 +    template <typename ItemWriter, typename Map>
   5.157 +    BpNodeSetWriter& writeNodeMap(std::string label, const Map& map, 
   5.158 +				  const ItemWriter& iw = ItemWriter()) {
   5.159 +      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
   5.160 +      checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
   5.161 +      writers.push_back(make_pair(label, new _writer_bits::
   5.162 +				  MapWriter<Node, Map, ItemWriter>(map, iw)));
   5.163 +      return *this;
   5.164 +    }
   5.165 +
   5.166 +  protected:
   5.167 +
   5.168 +    /// \brief The header of the section.
   5.169 +    ///
   5.170 +    /// It gives back the header of the section.
   5.171 +    virtual std::string header() {
   5.172 +      return "@bpnodeset " + name;
   5.173 +    }
   5.174 +
   5.175 +    /// \brief Writer function of the section.
   5.176 +    ///
   5.177 +    /// Write the content of the section.
   5.178 +    virtual void write(std::ostream& os) {
   5.179 +      for (int i = 0; i < int(writers.size()); ++i) {
   5.180 +	if (writers[i].first == "label") {
   5.181 +	  labelMap = writers[i].second;
   5.182 +	  forceLabelMap = false;
   5.183 +	  break;
   5.184 +	}
   5.185 +      }
   5.186 +      {
   5.187 +	os << "&anodeset ";
   5.188 +	std::vector<Node> items;
   5.189 +	for (typename Graph::ANodeIt it(graph); it != INVALID; ++it) {
   5.190 +	  items.push_back(it);
   5.191 +	}
   5.192 +	if (forceSort) {
   5.193 +	  if (labelMap) {
   5.194 +	    labelMap->sort(items);
   5.195 +	  } else {
   5.196 +	    typedef IdMap<Graph, Node> Map;
   5.197 +	    Map map(graph);
   5.198 +	    _writer_bits::ComposeLess<Map> less(map);
   5.199 +	    std::sort(items.begin(), items.end(), less);
   5.200 +	  }
   5.201 +	}
   5.202 +	if (forceLabelMap) {
   5.203 +	  os << "label\t";
   5.204 +	}
   5.205 +	for (int i = 0; i < int(writers.size()); ++i) {
   5.206 +	  os << writers[i].first << '\t';
   5.207 +	}
   5.208 +	for (int i = 0; i < int(awriters.size()); ++i) {
   5.209 +	  os << awriters[i].first << '\t';
   5.210 +	}
   5.211 +	os << std::endl;
   5.212 +	for (typename std::vector<Node>::iterator it = items.begin();
   5.213 +	     it != items.end(); ++it) {
   5.214 +	  if (forceLabelMap) {
   5.215 +	    os << graph.id(*it) << '\t';
   5.216 +	  }
   5.217 +	  for (int i = 0; i < int(writers.size()); ++i) {
   5.218 +	    writers[i].second->write(os, *it);
   5.219 +	    os << '\t';
   5.220 +	  }
   5.221 +	  for (int i = 0; i < int(awriters.size()); ++i) {
   5.222 +	    awriters[i].second->write(os, *it);
   5.223 +	    os << '\t';
   5.224 +	  }
   5.225 +	  os << std::endl;
   5.226 +	}
   5.227 +      }
   5.228 +      {
   5.229 +	os << "&bnodeset ";
   5.230 +	std::vector<Node> items;
   5.231 +	for (typename Graph::BNodeIt it(graph); it != INVALID; ++it) {
   5.232 +	  items.push_back(it);
   5.233 +	}
   5.234 +	if (forceSort) {
   5.235 +	  if (labelMap) {
   5.236 +	    labelMap->sort(items);
   5.237 +	  } else {
   5.238 +	    typedef IdMap<Graph, Node> Map;
   5.239 +	    Map map(graph);
   5.240 +	    _writer_bits::ComposeLess<Map> less(map);
   5.241 +	    std::sort(items.begin(), items.end(), less);
   5.242 +	  }
   5.243 +	}
   5.244 +	if (forceLabelMap) {
   5.245 +	  os << "label\t";
   5.246 +	}
   5.247 +	for (int i = 0; i < int(writers.size()); ++i) {
   5.248 +	  os << writers[i].first << '\t';
   5.249 +	}
   5.250 +	for (int i = 0; i < int(bwriters.size()); ++i) {
   5.251 +	  os << bwriters[i].first << '\t';
   5.252 +	}
   5.253 +	os << std::endl;
   5.254 +	for (typename std::vector<Node>::iterator it = items.begin();
   5.255 +	     it != items.end(); ++it) {
   5.256 +	  if (forceLabelMap) {
   5.257 +	    os << graph.id(*it) << '\t';
   5.258 +	  }
   5.259 +	  for (int i = 0; i < int(writers.size()); ++i) {
   5.260 +	    writers[i].second->write(os, *it);
   5.261 +	    os << '\t';
   5.262 +	  }
   5.263 +	  for (int i = 0; i < int(bwriters.size()); ++i) {
   5.264 +	    bwriters[i].second->write(os, *it);
   5.265 +	    os << '\t';
   5.266 +	  }
   5.267 +	  os << std::endl;
   5.268 +	}
   5.269 +      }
   5.270 +    }
   5.271 +
   5.272 +  public:
   5.273 +
   5.274 +    /// \brief Returns true if the nodeset can write the labels of the nodes.
   5.275 +    ///
   5.276 +    /// Returns true if the nodeset can write the labels of the nodes.
   5.277 +    /// It is possible only if a "label" named map was written or the 
   5.278 +    /// \c _forceLabelMap constructor parameter was true.
   5.279 +    bool isLabelWriter() const {
   5.280 +      return labelMap != 0 || forceLabelMap;
   5.281 +    }
   5.282 +
   5.283 +    /// \brief Write the label of the given node.
   5.284 +    ///
   5.285 +    /// It writes the label of the given node. If there was written a "label"
   5.286 +    /// named map then it will write the map value belongs to the node.
   5.287 +    /// Otherwise if the \c forceLabel parameter was true it will write
   5.288 +    /// its label in the graph. 
   5.289 +    void writeLabel(std::ostream& os, const Node& item) const {
   5.290 +      if (forceLabelMap) {
   5.291 +	os << graph.id(item);
   5.292 +      } else {
   5.293 +	labelMap->write(os, item);
   5.294 +      }
   5.295 +    }
   5.296 +
   5.297 +    /// \brief Sorts the given node vector by label.
   5.298 +    ///
   5.299 +    /// Sorts the given node vector by label. If there was written an
   5.300 +    /// "label" named map then the vector will be sorted by the values
   5.301 +    /// of this map. Otherwise if the \c forceLabel parameter was true
   5.302 +    /// it will be sorted by its id in the graph.
   5.303 +    void sortByLabel(std::vector<Node>& nodes) const {
   5.304 +      if (labelMap) {
   5.305 +	labelMap->sort(nodes);
   5.306 +      } else {
   5.307 +	typedef IdMap<Graph, Node> Map;
   5.308 +	Map map(graph);
   5.309 +	_writer_bits::ComposeLess<Map> less(map);
   5.310 +	std::sort(nodes.begin(), nodes.end(), less);
   5.311 +      }
   5.312 +    }
   5.313 +
   5.314 +  private:
   5.315 +
   5.316 +    typedef std::vector<std::pair<std::string, _writer_bits::
   5.317 +				  MapWriterBase<Node>*> > MapWriters;
   5.318 +    MapWriters awriters, bwriters, writers;
   5.319 +    
   5.320 +    _writer_bits::MapWriterBase<Node>* labelMap;
   5.321 +    bool forceLabelMap;
   5.322 +    bool forceSort;
   5.323 +   
   5.324 +    const Graph& graph;   
   5.325 +    std::string name;
   5.326 +
   5.327 +  };
   5.328 +
   5.329 +  /// \ingroup section_io
   5.330    /// \brief SectionWriter for writing a graph's edgesets.
   5.331    ///
   5.332    /// The lemon format can store multiple graph edgesets with several maps.