[Lemon-commits] deba: r3343 - in lemon/trunk: doc lemon
Lemon SVN
svn at lemon.cs.elte.hu
Wed Oct 24 18:31:50 CEST 2007
Author: deba
Date: Wed Oct 24 18:31:49 2007
New Revision: 3343
Modified:
lemon/trunk/doc/graph_io.dox
lemon/trunk/lemon/graph_reader.h
lemon/trunk/lemon/graph_writer.h
lemon/trunk/lemon/lemon_reader.h
lemon/trunk/lemon/lemon_writer.h
Log:
BpUGraphReader and Writer
Modified: lemon/trunk/doc/graph_io.dox
==============================================================================
--- lemon/trunk/doc/graph_io.dox (original)
+++ lemon/trunk/doc/graph_io.dox Wed Oct 24 18:31:49 2007
@@ -335,7 +335,7 @@
The specialization of writing is very similar to that of reading.
-\section u Undirected graphs
+\section undir Undirected and Bipartite graphs
In a file describing an undirected graph (ugraph, for short) you find an
\c uedgeset section instead of the \c edgeset section. The first line of
@@ -343,9 +343,9 @@
next lines describe one undirected edge with the the incident nodes and the
values of the map.
-The format handles directed edge maps as a syntactical sugar???, if there
-are two maps with names being the same with a \c '+' and a \c '-' prefix
-then this will be read as a directed map.
+The format could store directed edge maps, if there are two maps with
+names being the same with a \c '+' and a \c '-' prefix then this could
+be read as such a map.
\code
@uedgeset
@@ -386,6 +386,35 @@
reader.readEdge("edge", edge);
\endcode
+The undirected bipartite graphs could be read with the \c BpUGraph
+class and it has specialized nodeset section, which should be start
+with \c "@bpnodeset". This section is separated to two
+subsections. The header line of these sections start with "&anodeset"
+or "&bnodeset" and after that the line contains the names of the
+regular and A-node or B-node maps accordingly. The lines of each
+section contains the mapped values. The labels of the graph should be
+unique overall both subsections.
+
+\code
+ at bpnodeset
+&anodeset label coords radius
+ 0 (0, 0) 14.0
+ 1 (0, 1) 12.0
+&bnodeset label coords
+ 2 (1, 0)
+ 3 (1, 1)
+\endcode
+
+The reading can be done with \ref lemon::BpUGraphReader::readANodeMap()
+"readANodeMap()", \ref lemon::BpUGraphReader::readBNodeMap()
+"readBNodeMap()" or \ref lemon::BpUGraphReader::readNodeMap()
+"readNodeMap()" members.
+
+\code
+reader.readNodeMap("coords", coords);
+reader.readAnodeMap("radius", radius);
+\endcode
+
\section advanced Advanced features
The graph reader and writer classes give an easy way to read and write
Modified: lemon/trunk/lemon/graph_reader.h
==============================================================================
--- lemon/trunk/lemon/graph_reader.h (original)
+++ lemon/trunk/lemon/graph_reader.h Wed Oct 24 18:31:49 2007
@@ -725,6 +725,469 @@
AttributeReader<ReaderTraits> attribute_reader;
};
+ /// \brief The bipartite graph reader class.
+ ///
+ /// The \c BpUGraphReader class provides the graph input.
+ /// Before you read this documentation it might be useful to read the general
+ /// description of \ref graph-io-page "Graph Input-Output".
+ ///
+ /// The given file format may contain several maps and labeled nodes or
+ /// edges.
+ ///
+ /// If you read a graph you need not read all the maps and items just those
+ /// that you need. The interface of the \c BpUGraphReader is very similar
+ /// to the BpUGraphWriter but the reading method does not depend on the
+ /// order of the given commands.
+ ///
+ /// The reader object suppose that each not read value does not contain
+ /// whitespaces, therefore it has some extra possibilities to control how
+ /// it should skip the values when the string representation contains spaces.
+ ///
+ ///\code
+ /// BpUGraphReader<ListBpUGraph> reader(std::cin, graph);
+ ///\endcode
+ ///
+ /// The \c readANodeMap() function reads a map from the A-part of
+ /// the\c \@bpnodeset section, while the \c readBNodeMap() reads
+ /// from the B-part of the section. If you use the \c readNodeMap()
+ /// function, then the given map should appear in both part of the
+ /// section. If there is a map that you do not want to read from the
+ /// file and there is whitespace in the string represenation of the
+ /// values then you should call the \c skipANodeMap(), \c
+ /// skipBNodeMap() or \c skipNodeMap() template member function with
+ /// proper parameters.
+ ///
+ ///\code
+ /// reader.readNodeMap("coords", coords);
+ /// reader.readANodeMap("range", range);
+ /// reader.readANodeMap("benefit", benefit);
+ ///
+ /// reader.skipNodeMap("description", desc);
+ ///
+ /// reader.readNodeMap("color", colorMap);
+ ///\endcode
+ ///
+ /// With the \c readUEdgeMap() member function you can give an
+ /// uedge map reading command similar to the NodeMaps.
+ ///
+ ///\code
+ /// reader.readUEdgeMap("capacity", capacityMap);
+ /// reader.readEdgeMap("flow", flowMap);
+ ///\endcode
+ ///
+ /// With \c readNode() and \c readUEdge() functions you can read
+ /// labeled Nodes and UEdges.
+ ///
+ ///\code
+ /// reader.readNode("source", sourceNode);
+ /// reader.readNode("target", targetNode);
+ ///
+ /// reader.readUEdge("observed", uEdge);
+ ///\endcode
+ ///
+ /// With the \c readAttribute() functions you can read an attribute
+ /// in a variable. You can specify the reader for the attribute as
+ /// the nodemaps.
+ ///
+ /// After you give all read commands you must call the \c run() member
+ /// function, which execute all the commands.
+ ///
+ ///\code
+ /// reader.run();
+ ///\endcode
+ ///
+ /// \see GraphReader
+ /// \see DefaultReaderTraits
+ /// \see \ref UGraphWriter
+ /// \see \ref graph-io-page
+ ///
+ /// \author Balazs Dezso
+ template <typename _Graph, typename _ReaderTraits = DefaultReaderTraits>
+ class BpUGraphReader {
+ public:
+
+ typedef _Graph Graph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UEdge UEdge;
+
+ typedef _ReaderTraits ReaderTraits;
+ typedef typename ReaderTraits::Skipper DefaultSkipper;
+
+ /// \brief Construct a new BpUGraphReader.
+ ///
+ /// Construct a new BpUGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ BpUGraphReader(std::istream& _is, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(new LemonReader(_is)), own_reader(true), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ uedgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ uedge_reader(*reader, uedgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Construct a new BpUGraphReader.
+ ///
+ /// Construct a new BpUGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ BpUGraphReader(const std::string& _filename, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(new LemonReader(_filename)), own_reader(true),
+ skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ uedgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ uedge_reader(*reader, uedgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Construct a new BpUGraphReader.
+ ///
+ /// Construct a new BpUGraphReader. It reads into the given graph
+ /// and it use the given reader as the default skipper.
+ BpUGraphReader(LemonReader& _reader, Graph& _graph,
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : reader(_reader), own_reader(false), skipper(_skipper),
+ nodeset_reader(*reader, _graph, std::string(), skipper),
+ uedgeset_reader(*reader, _graph, nodeset_reader,
+ std::string(), skipper),
+ node_reader(*reader, nodeset_reader, std::string()),
+ uedge_reader(*reader, uedgeset_reader, std::string()),
+ attribute_reader(*reader, std::string()) {}
+
+ /// \brief Destruct the graph reader.
+ ///
+ /// Destruct the graph reader.
+ ~BpUGraphReader() {
+ if (own_reader)
+ delete reader;
+ }
+
+ /// \brief Give a new node map reading command to the reader.
+ ///
+ /// Give a new node map reading command to the reader.
+ template <typename Map>
+ BpUGraphReader& readNodeMap(std::string name, Map& map) {
+ nodeset_reader.readNodeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ BpUGraphReader& readNodeMap(std::string name, const Map& map) {
+ nodeset_reader.readNodeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Give a new node map reading command to the reader.
+ ///
+ /// Give a new node map reading command to the reader.
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readNodeMap(std::string name, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readNodeMap(name, map, ir);
+ return *this;
+ }
+
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readNodeMap(std::string name, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readNodeMap(name, map, ir);
+ return *this;
+ }
+
+ /// \brief Give a new node map skipping command to the reader.
+ ///
+ /// Give a new node map skipping command to the reader.
+ template <typename ItemReader>
+ BpUGraphReader& skipNodeMap(std::string name,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.skipNodeMap(name, ir);
+ return *this;
+ }
+
+ /// \brief Give a new A-node map reading command to the reader.
+ ///
+ /// Give a new A-node map reading command to the reader.
+ template <typename Map>
+ BpUGraphReader& readANodeMap(std::string name, Map& map) {
+ nodeset_reader.readANodeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ BpUGraphReader& readANodeMap(std::string name, const Map& map) {
+ nodeset_reader.readANodeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Give a new A-node map reading command to the reader.
+ ///
+ /// Give a new A-node map reading command to the reader.
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readANodeMap(std::string name, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readANodeMap(name, map, ir);
+ return *this;
+ }
+
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readANodeMap(std::string name, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readNodeMap(name, map, ir);
+ return *this;
+ }
+
+ /// \brief Give a new A-node map skipping command to the reader.
+ ///
+ /// Give a new A-node map skipping command to the reader.
+ template <typename ItemReader>
+ BpUGraphReader& skipANodeMap(std::string name,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.skipANodeMap(name, ir);
+ return *this;
+ }
+
+ /// \brief Give a new B-node map reading command to the reader.
+ ///
+ /// Give a new B-node map reading command to the reader.
+ template <typename Map>
+ BpUGraphReader& readBNodeMap(std::string name, Map& map) {
+ nodeset_reader.readBNodeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ BpUGraphReader& readBNodeMap(std::string name, const Map& map) {
+ nodeset_reader.readBNodeMap(name, map);
+ return *this;
+ }
+
+ /// \brief Give a new B-node map reading command to the reader.
+ ///
+ /// Give a new B-node map reading command to the reader.
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readBNodeMap(std::string name, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readBNodeMap(name, map, ir);
+ return *this;
+ }
+
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readBNodeMap(std::string name, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.readNodeMap(name, map, ir);
+ return *this;
+ }
+
+ /// \brief Give a new B-node map skipping command to the reader.
+ ///
+ /// Give a new B-node map skipping command to the reader.
+ template <typename ItemReader>
+ BpUGraphReader& skipBNodeMap(std::string name,
+ const ItemReader& ir = ItemReader()) {
+ nodeset_reader.skipBNodeMap(name, ir);
+ return *this;
+ }
+
+ /// \brief Give a new undirected edge map reading command to the reader.
+ ///
+ /// Give a new undirected edge map reading command to the reader.
+ template <typename Map>
+ BpUGraphReader& readUEdgeMap(std::string name, Map& map) {
+ uedgeset_reader.readUEdgeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ BpUGraphReader& readUEdgeMap(std::string name, const Map& map) {
+ uedgeset_reader.readUEdgeMap(name, map);
+ return *this;
+ }
+
+
+ /// \brief Give a new undirected edge map reading command to the reader.
+ ///
+ /// Give a new undirected edge map reading command to the reader.
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readUEdgeMap(std::string name, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.readUEdgeMap(name, map, ir);
+ return *this;
+ }
+
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readUEdgeMap(std::string name, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.readUEdgeMap(name, map, ir);
+ return *this;
+ }
+
+ /// \brief Give a new undirected edge map skipping command to the reader.
+ ///
+ /// Give a new undirected edge map skipping command to the reader.
+ template <typename ItemReader>
+ BpUGraphReader& skipUEdgeMap(std::string name,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.skipUMap(name, ir);
+ return *this;
+ }
+
+
+ /// \brief Give a new edge map reading command to the reader.
+ ///
+ /// Give a new edge map reading command to the reader.
+ template <typename Map>
+ BpUGraphReader& readEdgeMap(std::string name, Map& map) {
+ uedgeset_reader.readEdgeMap(name, map);
+ return *this;
+ }
+
+ template <typename Map>
+ BpUGraphReader& readEdgeMap(std::string name, const Map& map) {
+ uedgeset_reader.readEdgeMap(name, map);
+ return *this;
+ }
+
+
+ /// \brief Give a new edge map reading command to the reader.
+ ///
+ /// Give a new edge map reading command to the reader.
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readEdgeMap(std::string name, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.readEdgeMap(name, map, ir);
+ return *this;
+ }
+
+ template <typename ItemReader, typename Map>
+ BpUGraphReader& readEdgeMap(std::string name, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.readEdgeMap(name, map, ir);
+ return *this;
+ }
+
+ /// \brief Give a new edge map skipping command to the reader.
+ ///
+ /// Give a new edge map skipping command to the reader.
+ template <typename ItemReader>
+ BpUGraphReader& skipEdgeMap(std::string name,
+ const ItemReader& ir = ItemReader()) {
+ uedgeset_reader.skipEdgeMap(name, ir);
+ return *this;
+ }
+
+ /// \brief Give a new labeled node reading command to the reader.
+ ///
+ /// Give a new labeled node reading command to the reader.
+ BpUGraphReader& readNode(std::string name, Node& node) {
+ node_reader.readNode(name, node);
+ return *this;
+ }
+
+ /// \brief Give a new labeled edge reading command to the reader.
+ ///
+ /// Give a new labeled edge reading command to the reader.
+ BpUGraphReader& readEdge(std::string name, Edge& edge) {
+ uedge_reader.readEdge(name, edge);
+ }
+
+ /// \brief Give a new labeled undirected edge reading command to the
+ /// reader.
+ ///
+ /// Give a new labeled undirected edge reading command to the reader.
+ BpUGraphReader& readUEdge(std::string name, UEdge& edge) {
+ uedge_reader.readUEdge(name, edge);
+ }
+
+ /// \brief Give a new attribute reading command.
+ ///
+ /// Give a new attribute reading command.
+ template <typename Value>
+ BpUGraphReader& readAttribute(std::string name, Value& value) {
+ attribute_reader.readAttribute(name, value);
+ return *this;
+ }
+
+ /// \brief Give a new attribute reading command.
+ ///
+ /// Give a new attribute reading command.
+ template <typename ItemReader, typename Value>
+ BpUGraphReader& readAttribute(std::string name, Value& value,
+ const ItemReader& ir = ItemReader()) {
+ attribute_reader.readAttribute(name, value, ir);
+ return *this;
+ }
+
+ /// \brief Conversion operator to LemonReader.
+ ///
+ /// Conversion operator to LemonReader. It make possible
+ /// to access the encapsulated \e LemonReader, this way
+ /// you can attach to this reader new instances of
+ /// \e LemonReader::SectionReader.
+ operator LemonReader&() {
+ return *reader;
+ }
+
+ /// \brief Executes the reading commands.
+ ///
+ /// Executes the reading commands.
+ void run() {
+ reader->run();
+ }
+
+
+ /// \brief Returns true if the reader can give back the items by its label.
+ ///
+ /// Returns true if the reader can give back the items by its label.
+ bool isLabelReader() const {
+ return nodeset_reader.isLabelReader() &&
+ uedgeset_reader.isLabelReader();
+ }
+
+ /// \brief Gives back the node by its label.
+ ///
+ /// It reads an label from the stream and gives back which node belongs to
+ /// it. It is possible only if there was read a "label" named node map.
+ void readLabel(std::istream& is, Node& node) const {
+ return nodeset_reader.readLabel(is, node);
+ }
+
+ /// \brief Gives back the edge by its label
+ ///
+ /// It reads an label from the stream and gives back which edge belongs to
+ /// it. It is possible only if there was read a "label" named edge map.
+ void readLabel(std::istream& is, Edge& edge) const {
+ return uedgeset_reader.readLabel(is, edge);
+ }
+
+ /// \brief Gives back the undirected edge by its label.
+ ///
+ /// It reads an label from the stream and gives back which undirected edge
+ /// belongs to it. It is possible only if there was read a "label" named
+ /// edge map.
+ void readLabel(std::istream& is, UEdge& uedge) const {
+ return uedgeset_reader.readLabel(is, uedge);
+ }
+
+
+ private:
+
+ LemonReader* reader;
+ bool own_reader;
+
+ DefaultSkipper skipper;
+
+ BpNodeSetReader<Graph, ReaderTraits> nodeset_reader;
+ UEdgeSetReader<Graph, ReaderTraits> uedgeset_reader;
+
+ NodeReader<Graph> node_reader;
+ UEdgeReader<Graph> uedge_reader;
+
+ AttributeReader<ReaderTraits> attribute_reader;
+ };
+
/// @}
}
Modified: lemon/trunk/lemon/graph_writer.h
==============================================================================
--- lemon/trunk/lemon/graph_writer.h (original)
+++ lemon/trunk/lemon/graph_writer.h Wed Oct 24 18:31:49 2007
@@ -156,7 +156,7 @@
/// \brief Issue a new node map writing command for the writer.
///
- /// This function issues a new <i> node map writing command</i> to the writer.
+ /// This function issues a new <i> node map writing command</i> to the writer.
template <typename Map>
GraphWriter& writeNodeMap(std::string label, const Map& map) {
nodeset_writer.writeNodeMap(label, map);
@@ -166,7 +166,7 @@
/// \brief Issue a new node map writing command for the writer.
///
- /// This function issues a new <i> node map writing command</i> to the writer.
+ /// This function issues a new <i> node map writing command</i> to the writer.
template <typename ItemWriter, typename Map>
GraphWriter& writeNodeMap(std::string label, const Map& map,
const ItemWriter& iw = ItemWriter()) {
@@ -639,6 +639,376 @@
AttributeWriter<WriterTraits> attribute_writer;
};
+ /// \brief The bipartite graph writer class.
+ ///
+ /// The \c BpUGraphWriter class provides the ugraph output. To write
+ /// a graph you should first give writing commands to the writer. You can
+ /// declare write command as \c NodeMap, \c EdgeMap or \c UEdgeMap
+ /// writing and labeled Node, Edge or UEdge writing.
+ ///
+ ///\code
+ /// BpUGraphWriter<ListUGraph> writer(std::cout, graph);
+ ///\endcode
+ ///
+ /// The \c writeNodeMap() function declares a \c NodeMap writing
+ /// command in the \c BpUGraphWriter. You should give as parameter
+ /// the name of the map and the map object. The NodeMap writing
+ /// command with name "label" should write a unique map because it
+ /// is regarded as label map.
+ ///
+ ///\code
+ /// IdMap<ListUGraph, Node> nodeLabelMap;
+ /// writer.writeNodeMap("label", nodeLabelMap);
+ ///
+ /// writer.writeNodeMap("coords", coords);
+ /// writer.writeNodeMap("color", colorMap);
+ ///\endcode
+ ///
+ /// With the \c writeUEdgeMap() member function you can give an
+ /// undirected edge map writing command similar to the NodeMaps.
+ ///
+ ///\code
+ /// DescriptorMap<ListGraph, Edge, ListGraph::EdgeMap<int> >
+ /// edgeDescMap(graph);
+ /// writer.writeUEdgeMap("descriptor", edgeDescMap);
+ ///
+ /// writer.writeUEdgeMap("weight", weightMap);
+ /// writer.writeUEdgeMap("label", labelMap);
+ ///\endcode
+ ///
+ /// The EdgeMap handling is just a syntactical sugar. It writes
+ /// two undirected edge map with '+' and '-' prefix in the name.
+ ///
+ ///\code
+ /// writer.writeEdgeMap("capacity", capacityMap);
+ ///\endcode
+ ///
+ ///
+ /// With \c writeNode() and \c writeUEdge() functions you can
+ /// designate nodes and undirected edges in the graph. For example, you can
+ /// write out the source and target of the graph.
+ ///
+ ///\code
+ /// writer.writeNode("source", sourceNode);
+ /// writer.writeNode("target", targetNode);
+ ///
+ /// writer.writeUEdge("observed", uEdge);
+ ///\endcode
+ ///
+ /// After you give all write commands you must call the \c run() member
+ /// function, which executes all the writing commands.
+ ///
+ ///\code
+ /// writer.run();
+ ///\endcode
+ ///
+ /// \see DefaultWriterTraits
+ /// \see QuotedStringWriter
+ /// \see IdMap
+ /// \see DescriptorMap
+ /// \see \ref GraphWriter
+ /// \see \ref graph-io-page
+ /// \author Balazs Dezso
+ template <typename _Graph, typename _WriterTraits = DefaultWriterTraits>
+ class BpUGraphWriter {
+ public:
+
+ typedef _Graph Graph;
+ typedef typename Graph::Node Node;
+ typedef typename Graph::Edge Edge;
+ typedef typename Graph::UEdge UEdge;
+
+ typedef _WriterTraits WriterTraits;
+
+ /// \brief Construct a new BpUGraphWriter.
+ ///
+ /// Construct a new BpUGraphWriter. It writes the given graph
+ /// to the given stream.
+ BpUGraphWriter(std::ostream& _os, const Graph& _graph)
+ : writer(new LemonWriter(_os)), own_writer(true),
+ nodeset_writer(*writer, _graph, std::string()),
+ uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ uedge_writer(*writer, uedgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Construct a new BpUGraphWriter.
+ ///
+ /// Construct a new BpUGraphWriter. It writes the given graph
+ /// to the given file.
+ BpUGraphWriter(const std::string& _filename, const Graph& _graph)
+ : writer(new LemonWriter(_filename)), own_writer(true),
+ nodeset_writer(*writer, _graph, std::string()),
+ uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ uedge_writer(*writer, uedgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Construct a new BpUGraphWriter.
+ ///
+ /// Construct a new BpUGraphWriter. It writes the given graph
+ /// to given LemonWriter.
+ BpUGraphWriter(LemonWriter& _writer, const Graph& _graph)
+ : writer(_writer), own_writer(false),
+ nodeset_writer(*writer, _graph, std::string()),
+ uedgeset_writer(*writer, _graph, nodeset_writer, std::string()),
+ node_writer(*writer, nodeset_writer, std::string()),
+ uedge_writer(*writer, uedgeset_writer, std::string()),
+ attribute_writer(*writer, std::string()) {}
+
+ /// \brief Destruct the graph writer.
+ ///
+ /// Destruct the graph writer.
+ ~BpUGraphWriter() {
+ if (own_writer)
+ delete writer;
+ }
+
+ /// \brief Issue a new node map writing command to the writer.
+ ///
+ /// This function issues a new <i> node map writing command</i> to
+ /// the writer.
+ template <typename Map>
+ BpUGraphWriter& writeNodeMap(std::string label, const Map& map) {
+ nodeset_writer.writeNodeMap(label, map);
+ return *this;
+ }
+
+ /// \brief Issue a new node map writing command to the writer.
+ ///
+ /// This function issues a new <i> node map writing command</i> to
+ /// the writer.
+ template <typename ItemWriter, typename Map>
+ BpUGraphWriter& writeNodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ nodeset_writer.writeNodeMap(label, map, iw);
+ return *this;
+ }
+
+ /// \brief Issue a new A-node map writing command to the writer.
+ ///
+ /// This function issues a new <i> A-node map writing command</i> to
+ /// the writer.
+ template <typename Map>
+ BpUGraphWriter& writeANodeMap(std::string label, const Map& map) {
+ nodeset_writer.writeANodeMap(label, map);
+ return *this;
+ }
+
+ /// \brief Issue a new A-node map writing command to the writer.
+ ///
+ /// This function issues a new <i> A-node map writing command</i> to
+ /// the writer.
+ template <typename ItemWriter, typename Map>
+ BpUGraphWriter& writeANodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ nodeset_writer.writeANodeMap(label, map, iw);
+ return *this;
+ }
+ /// \brief Issue a new B-node map writing command to the writer.
+ ///
+ /// This function issues a new <i> B-node map writing command</i> to
+ /// the writer.
+ template <typename Map>
+ BpUGraphWriter& writeBNodeMap(std::string label, const Map& map) {
+ nodeset_writer.writeBNodeMap(label, map);
+ return *this;
+ }
+
+ /// \brief Issue a new B-node map writing command to the writer.
+ ///
+ /// This function issues a new <i> B-node map writing command</i> to
+ /// the writer.
+ template <typename ItemWriter, typename Map>
+ BpUGraphWriter& writeBNodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ nodeset_writer.writeBNodeMap(label, map, iw);
+ return *this;
+ }
+
+ /// \brief Issue a new edge map writing command to the writer.
+ ///
+ /// This function issues a new <i> edge map writing command</i> to
+ /// the writer.
+ template <typename Map>
+ BpUGraphWriter& writeEdgeMap(std::string label, const Map& map) {
+ uedgeset_writer.writeEdgeMap(label, map);
+ return *this;
+ }
+
+ /// \brief Issue a new edge map writing command to the writer.
+ ///
+ /// This function issues a new <i> edge map writing command</i> to
+ /// the writer.
+ template <typename ItemWriter, typename Map>
+ BpUGraphWriter& writeEdgeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ uedgeset_writer.writeEdgeMap(label, map, iw);
+ return *this;
+ }
+
+ /// \brief Issue a new undirected edge map writing command to the writer.
+ ///
+ /// This function issues a new <i> undirected edge map writing
+ /// command</i> to the writer.
+ template <typename Map>
+ BpUGraphWriter& writeUEdgeMap(std::string label, const Map& map) {
+ uedgeset_writer.writeUEdgeMap(label, map);
+ return *this;
+ }
+
+ /// \brief Issue a new undirected edge map writing command to the writer.
+ ///
+ /// This function issues a new <i> undirected edge map writing
+ /// command</i> to the writer.
+ template <typename ItemWriter, typename Map>
+ BpUGraphWriter& writeUEdgeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ uedgeset_writer.writeUEdgeMap(label, map, iw);
+ return *this;
+ }
+
+ /// \brief Issue a new labeled node writer to the writer.
+ ///
+ /// This function issues a new <i> labeled node writing
+ /// command</i> to the writer.
+ BpUGraphWriter& writeNode(std::string label, const Node& node) {
+ node_writer.writeNode(label, node);
+ return *this;
+ }
+
+ /// \brief Issue a new labeled edge writer to the writer.
+ ///
+ /// This function issues a new <i> labeled edge writing
+ /// command</i> to the writer.
+ BpUGraphWriter& writeEdge(std::string label, const Edge& edge) {
+ uedge_writer.writeEdge(label, edge);
+ }
+
+ /// \brief Issue a new labeled undirected edge writing command to
+ /// the writer.
+ ///
+ /// Issue a new <i>labeled undirected edge writing command</i> to
+ /// the writer.
+ BpUGraphWriter& writeUEdge(std::string label, const UEdge& edge) {
+ uedge_writer.writeUEdge(label, edge);
+ }
+
+ /// \brief Issue a new attribute writing command.
+ ///
+ /// This function issues a new <i> attribute writing
+ /// command</i> to the writer.
+ template <typename Value>
+ BpUGraphWriter& writeAttribute(std::string label, const Value& value) {
+ attribute_writer.writeAttribute(label, value);
+ return *this;
+ }
+
+ /// \brief Issue a new attribute writing command.
+ ///
+ /// This function issues a new <i> attribute writing
+ /// command</i> to the writer.
+ template <typename ItemWriter, typename Value>
+ BpUGraphWriter& writeAttribute(std::string label, const Value& value,
+ const ItemWriter& iw = ItemWriter()) {
+ attribute_writer.writeAttribute(label, value, iw);
+ return *this;
+ }
+
+ /// \brief Conversion operator to LemonWriter.
+ ///
+ /// Conversion operator to LemonWriter. It makes possible
+ /// to access the encapsulated \e LemonWriter, this way
+ /// you can attach to this writer new instances of
+ /// \e LemonWriter::SectionWriter.
+ operator LemonWriter&() {
+ return *writer;
+ }
+
+ /// \brief Executes the writing commands.
+ ///
+ /// Executes the writing commands.
+ void run() {
+ writer->run();
+ }
+
+ /// \brief Returns true if the writer can give back the labels by the items.
+ ///
+ /// Returns true if the writer can give back the the labels by the items.
+ bool isLabelWriter() const {
+ return nodeset_writer.isLabelWriter() &&
+ uedgeset_writer.isLabelWriter();
+ }
+
+ /// \brief Write the label of the given node.
+ ///
+ /// It writes the label of the given node. If there was written a "label"
+ /// named node map then it will write the map value belonging to the node.
+ void writeLabel(std::ostream& os, const Node& item) const {
+ nodeset_writer.writeLabel(os, item);
+ }
+
+ /// \brief Write the label of the given edge.
+ ///
+ /// It writes the label of the given edge. If there was written a "label"
+ /// named edge map then it will write the map value belonging to the edge.
+ void writeLabel(std::ostream& os, const Edge& item) const {
+ uedgeset_writer.writeLabel(os, item);
+ }
+
+ /// \brief Write the label of the given undirected edge.
+ ///
+ /// It writes the label of the given undirected edge. If there was
+ /// written a "label" named edge map then it will write the map
+ /// value belonging to the edge.
+ void writeLabel(std::ostream& os, const UEdge& item) const {
+ uedgeset_writer.writeLabel(os, item);
+ }
+
+ /// \brief Sorts the given node vector by label.
+ ///
+ /// Sorts the given node vector by label. If there was written an
+ /// "label" named map then the vector will be sorted by the values
+ /// of this map. Otherwise if the \c forceLabel parameter was true
+ /// it will be sorted by its id in the graph.
+ void sortByLabel(std::vector<Node>& nodes) const {
+ nodeset_writer.sortByLabel(nodes);
+ }
+
+ /// \brief Sorts the given edge vector by label.
+ ///
+ /// Sorts the given edge vector by label. If there was written an
+ /// "label" named map then the vector will be sorted by the values
+ /// of this map. Otherwise if the \c forceLabel parameter was true
+ /// it will be sorted by its id in the graph.
+ void sortByLabel(std::vector<Edge>& edges) const {
+ uedgeset_writer.sortByLabel(edges);
+ }
+
+ /// \brief Sorts the given undirected edge vector by label.
+ ///
+ /// Sorts the given undirected edge vector by label. If there was
+ /// written an "label" named map then the vector will be sorted by
+ /// the values of this map. Otherwise if the \c forceLabel
+ /// parameter was true it will be sorted by its id in the graph.
+ void sortByLabel(std::vector<UEdge>& uedges) const {
+ uedgeset_writer.sortByLabel(uedges);
+ }
+
+ private:
+
+ LemonWriter* writer;
+ bool own_writer;
+
+ BpNodeSetWriter<Graph, WriterTraits> nodeset_writer;
+ UEdgeSetWriter<Graph, WriterTraits> uedgeset_writer;
+
+ NodeWriter<Graph> node_writer;
+ UEdgeWriter<Graph> uedge_writer;
+
+ AttributeWriter<WriterTraits> attribute_writer;
+ };
+
/// @}
}
Modified: lemon/trunk/lemon/lemon_reader.h
==============================================================================
--- lemon/trunk/lemon/lemon_reader.h (original)
+++ lemon/trunk/lemon/lemon_reader.h Wed Oct 24 18:31:49 2007
@@ -311,7 +311,7 @@
MapReaderBase() { _touched = false; }
- void touch() { _touched = true; }
+ void touch(bool value = true) { _touched = value; }
bool touched() const { return _touched; }
virtual ~MapReaderBase() {}
@@ -593,8 +593,7 @@
virtual int_type underflow() {
char c;
- if (_is.read(&c, 1)) {
- _is.putback(c);
+ if ((c = _is.peek()) != EOF) {
if (c == '@') {
return EOF;
}
@@ -603,13 +602,13 @@
}
char_type *ptr;
for (ptr = base(); ptr != eptr(); ++ptr) {
- if (_is.read(&c, 1)) {
+ if ((c = _is.get()) != EOF) {
if (c == '\n') ++_num;
if (put_char(c)) {
*ptr = c;
} else {
if (skip_state == after_endl && c == '@') {
- _is.putback('@');
+ _is.putback(c);
break;
}
--ptr;
@@ -638,6 +637,36 @@
};
+ static void skipPreSection(std::istream& is, int& line_num) {
+ enum skip_state_type { skip, after_endl };
+
+ skip_state_type skip_state = after_endl;
+ char c;
+
+ while ((c = is.get()) != EOF) {
+ if (c == '\n') ++line_num;
+
+ switch (skip_state) {
+ case skip:
+ if (c == '\n') skip_state = after_endl;
+ break;
+ case after_endl:
+ switch (c) {
+ case '@':
+ is.putback(c);
+ return;
+ case '\n':
+ continue;
+ default:
+ if (!isspace(c)) {
+ skip_state = skip;
+ }
+ break;
+ }
+ }
+ }
+ }
+
public:
/// \brief Abstract base class for reading a section.
@@ -722,6 +751,7 @@
std::string line;
SectionReaders::iterator it;
+ skipPreSection(*is, line_num);
while ((++line_num, getline(*is, line)) && line.find("@end") != 0) {
for (it = readers.begin(); it != readers.end(); ++it) {
if (it->first->header(line)) {
@@ -732,6 +762,7 @@
buffer.pubsetbuf(buf, sizeof(buf));
std::istream ss(&buffer);
it->first->read(ss);
+ skipPreSection(*is, line_num);
break;
} catch (DataFormatError& error) {
error.line(buffer.line_num());
@@ -984,6 +1015,465 @@
};
/// \ingroup section_io
+ /// \brief SectionReader for reading a bipartite graph's nodeset.
+ ///
+ /// The lemon format can store multiple bipartite graph nodesets
+ /// with several maps. The bipartite graph nodeset section's header
+ /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name
+ /// may be empty.
+ ///
+ /// The first line of the section contains \c "&anodeset" and the
+ /// the names of the A-node maps and regular maps separated with
+ /// white spaces. Each next lines describes an A-node in the anodeset,
+ /// and contains the mapped values for each map. If one of the line
+ /// starts with \c "&bnodeset" then this line contains the names of
+ /// the B-node maps and the regular node maps. And the remaining lines
+ /// contains the mapped values to the B-nodes.
+ ///
+ /// If there is "label" named map then it should be defined in both
+ /// nodeset, and it will be regarded as id map. This map should
+ /// contain only unique values and when the \c readLabel() member
+ /// will read a value from the given stream it will give back that
+ /// node which is mapped to this value.
+ ///
+ /// \relates LemonReader
+ template <typename _Graph, typename _Traits = DefaultReaderTraits>
+ class BpNodeSetReader : public LemonReader::SectionReader {
+ typedef LemonReader::SectionReader Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::Node Node;
+ typedef typename Traits::Skipper DefaultSkipper;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and
+ /// attach it into the given LemonReader. The nodeset reader will
+ /// add the read nodes to the given Graph. The reader will read
+ /// the section when the \c section_name and the \c _name are the same.
+ BpNodeSetReader(LemonReader& _reader,
+ Graph& _graph,
+ const std::string& _name = std::string(),
+ const DefaultSkipper& _skipper = DefaultSkipper())
+ : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {}
+
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for BpNodeSetReader.
+ virtual ~BpNodeSetReader() {
+ for (typename MapReaders::iterator it = readers.begin();
+ it != readers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ BpNodeSetReader(const BpNodeSetReader&);
+ void operator=(const BpNodeSetReader&);
+
+ public:
+
+ /// \brief Add a new node map reader command for the reader.
+ ///
+ /// Add a new node map reader command for the reader.
+ template <typename Map>
+ BpNodeSetReader& readNodeMap(std::string label, Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ template <typename Map>
+ BpNodeSetReader& readNodeMap(std::string label, const Map& map) {
+ return _readMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ /// \brief Add a new node map reader command for the reader.
+ ///
+ /// Add a new node map reader command for the reader.
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readNodeMap(std::string label, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readNodeMap(std::string label, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ private:
+
+ template <typename ItemReader, typename Map, typename MapParameter>
+ BpNodeSetReader& _readMap(std::string label, MapParameter map,
+ const ItemReader& ir = ItemReader()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+ if (areaders.find(label) != areaders.end() ||
+ breaders.find(label) != breaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ readers.insert(make_pair(label, new _reader_bits::
+ MapReader<Node, Map, ItemReader>(map, ir)));
+ return *this;
+ }
+
+ public:
+
+ /// \brief Add a new A-node map reader command for the reader.
+ ///
+ /// Add a new A-node map reader command for the reader.
+ template <typename Map>
+ BpNodeSetReader& readANodeMap(std::string label, Map& map) {
+ return _readAMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ template <typename Map>
+ BpNodeSetReader& readANodeMap(std::string label, const Map& map) {
+ return _readAMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ /// \brief Add a new A-node map reader command for the reader.
+ ///
+ /// Add a new A-node map reader command for the reader.
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readANodeMap(std::string label, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readANodeMap(std::string label, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ private:
+
+ template <typename ItemReader, typename Map, typename MapParameter>
+ BpNodeSetReader& _readAMap(std::string label, MapParameter map,
+ const ItemReader& ir = ItemReader()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+ if (label == "label") {
+ throw IoParameterError("Label cannot be A-node map");
+ }
+ if (areaders.find(label) != areaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for A-node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ areaders.insert(make_pair(label, new _reader_bits::
+ MapReader<Node, Map, ItemReader>(map, ir)));
+ return *this;
+ }
+
+ public:
+
+ /// \brief Add a new B-node map reader command for the reader.
+ ///
+ /// Add a new B-node map reader command for the reader.
+ template <typename Map>
+ BpNodeSetReader& readBNodeMap(std::string label, Map& map) {
+ return _readBMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ template <typename Map>
+ BpNodeSetReader& readBNodeMap(std::string label, const Map& map) {
+ return _readBMap<
+ typename Traits::template Reader<typename Map::Value>, Map,
+ typename _reader_bits::Arg<Map>::Type>(label, map);
+ }
+
+ /// \brief Add a new B-node map reader command for the reader.
+ ///
+ /// Add a new B-node map reader command for the reader.
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readBNodeMap(std::string label, Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ template <typename ItemReader, typename Map>
+ BpNodeSetReader& readBNodeMap(std::string label, const Map& map,
+ const ItemReader& ir = ItemReader()) {
+ return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type>
+ (label, map, ir);
+ }
+
+ private:
+
+ template <typename ItemReader, typename Map, typename MapParameter>
+ BpNodeSetReader& _readBMap(std::string label, MapParameter map,
+ const ItemReader& ir = ItemReader()) {
+ checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
+ checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>();
+ if (label == "label") {
+ throw IoParameterError("Label cannot be B-node map");
+ }
+ if (breaders.find(label) != breaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for B-node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ breaders.insert(make_pair(label, new _reader_bits::
+ MapReader<Node, Map, ItemReader>(map, ir)));
+ return *this;
+ }
+
+ public:
+
+ /// \brief Add a new node map skipper command for the reader.
+ ///
+ /// Add a new node map skipper command for the reader.
+ template <typename ItemReader>
+ BpNodeSetReader& skipNodeMap(std::string label,
+ const ItemReader& ir = ItemReader()) {
+ if (areaders.find(label) != areaders.end() ||
+ breaders.find(label) != breaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ readers.insert(make_pair(label, new _reader_bits::
+ SkipReader<Node, ItemReader>(ir)));
+ return *this;
+ }
+
+ /// \brief Add a new A-node map skipper command for the reader.
+ ///
+ /// Add a new A-node map skipper command for the reader.
+ template <typename ItemReader>
+ BpNodeSetReader& skipANodeMap(std::string label,
+ const ItemReader& ir = ItemReader()) {
+ if (label == "label") {
+ throw IoParameterError("Label cannot be A-node map");
+ }
+ if (areaders.find(label) != areaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for A-node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ areaders.insert(make_pair(label, new _reader_bits::
+ SkipReader<Node, ItemReader>(ir)));
+ return *this;
+ }
+
+ /// \brief Add a new B-node map skipper command for the reader.
+ ///
+ /// Add a new B-node map skipper command for the reader.
+ template <typename ItemReader>
+ BpNodeSetReader& skipBNodeMap(std::string label,
+ const ItemReader& ir = ItemReader()) {
+ if (label == "label") {
+ throw IoParameterError("Label cannot be B-node map");
+ }
+ if (breaders.find(label) != breaders.end() ||
+ readers.find(label) != readers.end()) {
+ ErrorMessage msg;
+ msg << "Multiple read rule for B-node map: " << label;
+ throw IoParameterError(msg.message());
+ }
+ breaders.insert(make_pair(label, new _reader_bits::
+ SkipReader<Node, ItemReader>(ir)));
+ return *this;
+ }
+
+
+ protected:
+
+ /// \brief Gives back true when the SectionReader can process
+ /// the section with the given header line.
+ ///
+ /// It gives back true when the header line starts with \c \@nodeset,
+ /// and the header line's name and the nodeset's name are the same.
+ virtual bool header(const std::string& line) {
+ std::istringstream ls(line);
+ std::string command;
+ std::string id;
+ ls >> command >> id;
+ return command == "@bpnodeset" && name == id;
+ }
+
+ /// \brief Reader function of the section.
+ ///
+ /// It reads the content of the section.
+ virtual void read(std::istream& is) {
+ std::string line;
+ {
+ std::vector<_reader_bits::MapReaderBase<Node>* > index;
+ {
+ getline(is, line);
+ std::istringstream ls(line);
+ std::string id;
+ ls >> id;
+ if (id != "&anodeset") {
+ throw IoParameterError("Cannot find &anodeset subsection");
+ }
+ while (ls >> id) {
+ typename MapReaders::iterator it = readers.find(id);
+ typename MapReaders::iterator ait = areaders.find(id);
+ if (it != readers.end()) {
+ it->second->touch();
+ index.push_back(it->second);
+ } else if (ait != areaders.end()) {
+ ait->second->touch();
+ index.push_back(ait->second);
+ }
+ if (id == "label") {
+ inverter.reset(index.back()->getInverter());
+ index.back() = inverter.get();
+ }
+ }
+ }
+ for (typename MapReaders::iterator it = areaders.begin();
+ it != areaders.end(); ++it) {
+ if (!it->second->touched()) {
+ ErrorMessage msg;
+ msg << "Map not found in file: " << it->first;
+ throw IoParameterError(msg.message());
+ }
+ }
+ for (typename MapReaders::iterator it = readers.begin();
+ it != readers.end(); ++it) {
+ if (!it->second->touched()) {
+ ErrorMessage msg;
+ msg << "Map not found in file: " << it->first;
+ throw IoParameterError(msg.message());
+ }
+ it->second->touch(false);
+ }
+
+ while (getline(is, line)) {
+ if (line[0] == '&') {
+ std::istringstream ls(line);
+ std::string id;
+ ls >> id;
+ if (id == "&bnodeset") break;
+ }
+ Node node = graph.addANode();
+ std::istringstream ls(line);
+ for (int i = 0; i < int(index.size()); ++i) {
+ index[i]->read(ls, node);
+ }
+ }
+ }
+
+ {
+ std::vector<_reader_bits::MapReaderBase<Node>* > index;
+ {
+ std::istringstream ls(line);
+ std::string id;
+ ls >> id;
+ if (id != "&bnodeset") {
+ throw IoParameterError("Cannot find &bnodeset subsection");
+ }
+ while (ls >> id) {
+ typename MapReaders::iterator it = readers.find(id);
+ typename MapReaders::iterator bit = breaders.find(id);
+ if (it != readers.end()) {
+ it->second->touch();
+ index.push_back(it->second);
+ } else if (bit != breaders.end()) {
+ bit->second->touch();
+ index.push_back(bit->second);
+ }
+ if (id == "label" && inverter.get() != 0) {
+ index.back() = inverter.get();
+ }
+ }
+ }
+ for (typename MapReaders::iterator it = breaders.begin();
+ it != breaders.end(); ++it) {
+ if (!it->second->touched()) {
+ ErrorMessage msg;
+ msg << "Map not found in file: " << it->first;
+ throw IoParameterError(msg.message());
+ }
+ }
+ for (typename MapReaders::iterator it = readers.begin();
+ it != readers.end(); ++it) {
+ if (!it->second->touched()) {
+ ErrorMessage msg;
+ msg << "Map not found in file: " << it->first;
+ throw IoParameterError(msg.message());
+ }
+ }
+ while (getline(is, line)) {
+ Node node = graph.addBNode();
+ std::istringstream ls(line);
+ for (int i = 0; i < int(index.size()); ++i) {
+ index[i]->read(ls, node);
+ }
+ }
+ }
+ }
+
+ virtual void missing() {
+ if (readers.empty()) return;
+ ErrorMessage msg;
+ msg << "BpNodeSet section not found in file: @bpnodeset " << name;
+ throw IoParameterError(msg.message());
+ }
+
+ public:
+
+ /// \brief Returns true if the nodeset can give back the node by its label.
+ ///
+ /// Returns true if the nodeset can give back the node by its label.
+ /// It is possible only if an "label" named map was read.
+ bool isLabelReader() const {
+ return inverter.get() != 0;
+ }
+
+ /// \brief Gives back the node by its label.
+ ///
+ /// It reads an id from the stream and gives back which node belongs to
+ /// it. It is possible only if there was read an "label" named map.
+ void readLabel(std::istream& is, Node& node) const {
+ node = inverter->read(is);
+ }
+
+ private:
+
+ typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*>
+ MapReaders;
+
+ MapReaders areaders, breaders, readers;
+
+ Graph& graph;
+ std::string name;
+ _reader_bits::SkipReader<Node, DefaultSkipper> skipper;
+
+ std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter;
+ };
+
+
+ /// \ingroup section_io
/// \brief SectionReader for reading a graph's edgeset.
///
/// The lemon format can store multiple graph edgesets with several maps.
Modified: lemon/trunk/lemon/lemon_writer.h
==============================================================================
--- lemon/trunk/lemon/lemon_writer.h (original)
+++ lemon/trunk/lemon/lemon_writer.h Wed Oct 24 18:31:49 2007
@@ -144,8 +144,8 @@
}
private:
- typename Ref<Map>::Type map;
const Graph& graph;
+ typename Ref<Map>::Type map;
};
template <typename Graph, typename Map>
@@ -168,8 +168,8 @@
}
private:
- typename Ref<Map>::Type map;
const Graph& graph;
+ typename Ref<Map>::Type map;
};
template <typename Graph, typename Map>
@@ -502,7 +502,7 @@
/// \c writeLabel() member will be called with a node it will write it's
/// label. Otherwise if the \c _forceLabelMap constructor parameter is true
/// then the label map will be the id in the graph. In addition if the
- /// the \c _forceSort is true then the writer will write the edges
+ /// the \c _forceSort is true then the writer will write the nodes
/// sorted by the labels.
///
/// \relates LemonWriter
@@ -680,6 +680,300 @@
};
/// \ingroup section_io
+ /// \brief SectionWriter for writing a bipartite graph's nodeset.
+ ///
+ /// The lemon format can store multiple bipartite graph nodesets
+ /// with several maps. The nodeset section's header line is \c
+ /// \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name may be empty.
+ ///
+ /// The first line of the section contains the names of the maps separated
+ /// with white spaces. Each next lines describes a node in the nodeset, and
+ /// contains the mapped values for each map.
+ ///
+ /// If the nodeset contains an \c "label" named map then it will be regarded
+ /// as label map. This map should contain only unique values and when the
+ /// \c writeLabel() member will be called with a node it will write it's
+ /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
+ /// then the label map will be the id in the graph. In addition if the
+ /// the \c _forceSort is true then the writer will write the edges
+ /// sorted by the labels.
+ ///
+ /// \relates LemonWriter
+ template <typename _Graph, typename _Traits = DefaultWriterTraits>
+ class BpNodeSetWriter : public LemonWriter::SectionWriter {
+ typedef LemonWriter::SectionWriter Parent;
+ public:
+
+ typedef _Graph Graph;
+ typedef _Traits Traits;
+ typedef typename Graph::Node Node;
+
+ /// \brief Constructor.
+ ///
+ /// Constructor for BpNodeSetWriter. It creates the BpNodeSetWriter and
+ /// attach it into the given LemonWriter. If the \c _forceLabelMap
+ /// parameter is true then the writer will write own label map when
+ /// the user does not give "label" named map. In addition if the
+ /// the \c _forceSort is true then the writer will write the nodes
+ /// sorted by the labels.
+ BpNodeSetWriter(LemonWriter& _writer, const Graph& _graph,
+ const std::string& _name = std::string(),
+ bool _forceLabelMap = true, bool _forceSort = true)
+ : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
+ forceSort(_forceSort), graph(_graph), name(_name) {}
+
+ /// \brief Destructor.
+ ///
+ /// Destructor for BpNodeSetWriter.
+ virtual ~BpNodeSetWriter() {
+ typename MapWriters::iterator it;
+ for (it = writers.begin(); it != writers.end(); ++it) {
+ delete it->second;
+ }
+ }
+
+ private:
+ BpNodeSetWriter(const BpNodeSetWriter&);
+ void operator=(const BpNodeSetWriter&);
+
+ public:
+
+ /// \brief Add a new A-node map writer command for the writer.
+ ///
+ /// Add a new A-node map writer command for the writer.
+ template <typename Map>
+ BpNodeSetWriter& writeANodeMap(std::string label, const Map& map) {
+ return writeANodeMap<typename Traits::
+ template Writer<typename Map::Value>, Map>(label, map);
+ }
+
+ /// \brief Add a new A-node map writer command for the writer.
+ ///
+ /// Add a new A-node map writer command for the writer.
+ template <typename ItemWriter, typename Map>
+ BpNodeSetWriter& writeANodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+ if (label == "label") {
+ throw IoParameterError("Label cannot be A-node map");
+ }
+ awriters.push_back(make_pair(label, new _writer_bits::
+ MapWriter<Node, Map, ItemWriter>(map, iw)));
+ return *this;
+ }
+
+ /// \brief Add a new B-node map writer command for the writer.
+ ///
+ /// Add a new B-node map writer command for the writer.
+ template <typename Map>
+ BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map) {
+ return writeBNodeMap<typename Traits::
+ template Writer<typename Map::Value>, Map>(label, map);
+ }
+
+ /// \brief Add a new B-node map writer command for the writer.
+ ///
+ /// Add a new B-node map writer command for the writer.
+ template <typename ItemWriter, typename Map>
+ BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+ if (label == "label") {
+ throw IoParameterError("Label cannot be B-node map");
+ }
+ bwriters.push_back(make_pair(label, new _writer_bits::
+ MapWriter<Node, Map, ItemWriter>(map, iw)));
+ return *this;
+ }
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// Add a new node map writer command for the writer.
+ template <typename Map>
+ BpNodeSetWriter& writeNodeMap(std::string label, const Map& map) {
+ return writeNodeMap<typename Traits::
+ template Writer<typename Map::Value>, Map>(label, map);
+ }
+
+ /// \brief Add a new node map writer command for the writer.
+ ///
+ /// Add a new node map writer command for the writer.
+ template <typename ItemWriter, typename Map>
+ BpNodeSetWriter& writeNodeMap(std::string label, const Map& map,
+ const ItemWriter& iw = ItemWriter()) {
+ checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
+ checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
+ writers.push_back(make_pair(label, new _writer_bits::
+ MapWriter<Node, Map, ItemWriter>(map, iw)));
+ return *this;
+ }
+
+ protected:
+
+ /// \brief The header of the section.
+ ///
+ /// It gives back the header of the section.
+ virtual std::string header() {
+ return "@bpnodeset " + name;
+ }
+
+ /// \brief Writer function of the section.
+ ///
+ /// Write the content of the section.
+ virtual void write(std::ostream& os) {
+ for (int i = 0; i < int(writers.size()); ++i) {
+ if (writers[i].first == "label") {
+ labelMap = writers[i].second;
+ forceLabelMap = false;
+ break;
+ }
+ }
+ {
+ os << "&anodeset ";
+ std::vector<Node> items;
+ for (typename Graph::ANodeIt it(graph); it != INVALID; ++it) {
+ items.push_back(it);
+ }
+ if (forceSort) {
+ if (labelMap) {
+ labelMap->sort(items);
+ } else {
+ typedef IdMap<Graph, Node> Map;
+ Map map(graph);
+ _writer_bits::ComposeLess<Map> less(map);
+ std::sort(items.begin(), items.end(), less);
+ }
+ }
+ if (forceLabelMap) {
+ os << "label\t";
+ }
+ for (int i = 0; i < int(writers.size()); ++i) {
+ os << writers[i].first << '\t';
+ }
+ for (int i = 0; i < int(awriters.size()); ++i) {
+ os << awriters[i].first << '\t';
+ }
+ os << std::endl;
+ for (typename std::vector<Node>::iterator it = items.begin();
+ it != items.end(); ++it) {
+ if (forceLabelMap) {
+ os << graph.id(*it) << '\t';
+ }
+ for (int i = 0; i < int(writers.size()); ++i) {
+ writers[i].second->write(os, *it);
+ os << '\t';
+ }
+ for (int i = 0; i < int(awriters.size()); ++i) {
+ awriters[i].second->write(os, *it);
+ os << '\t';
+ }
+ os << std::endl;
+ }
+ }
+ {
+ os << "&bnodeset ";
+ std::vector<Node> items;
+ for (typename Graph::BNodeIt it(graph); it != INVALID; ++it) {
+ items.push_back(it);
+ }
+ if (forceSort) {
+ if (labelMap) {
+ labelMap->sort(items);
+ } else {
+ typedef IdMap<Graph, Node> Map;
+ Map map(graph);
+ _writer_bits::ComposeLess<Map> less(map);
+ std::sort(items.begin(), items.end(), less);
+ }
+ }
+ if (forceLabelMap) {
+ os << "label\t";
+ }
+ for (int i = 0; i < int(writers.size()); ++i) {
+ os << writers[i].first << '\t';
+ }
+ for (int i = 0; i < int(bwriters.size()); ++i) {
+ os << bwriters[i].first << '\t';
+ }
+ os << std::endl;
+ for (typename std::vector<Node>::iterator it = items.begin();
+ it != items.end(); ++it) {
+ if (forceLabelMap) {
+ os << graph.id(*it) << '\t';
+ }
+ for (int i = 0; i < int(writers.size()); ++i) {
+ writers[i].second->write(os, *it);
+ os << '\t';
+ }
+ for (int i = 0; i < int(bwriters.size()); ++i) {
+ bwriters[i].second->write(os, *it);
+ os << '\t';
+ }
+ os << std::endl;
+ }
+ }
+ }
+
+ public:
+
+ /// \brief Returns true if the nodeset can write the labels of the nodes.
+ ///
+ /// Returns true if the nodeset can write the labels of the nodes.
+ /// It is possible only if a "label" named map was written or the
+ /// \c _forceLabelMap constructor parameter was true.
+ bool isLabelWriter() const {
+ return labelMap != 0 || forceLabelMap;
+ }
+
+ /// \brief Write the label of the given node.
+ ///
+ /// It writes the label of the given node. If there was written a "label"
+ /// named map then it will write the map value belongs to the node.
+ /// Otherwise if the \c forceLabel parameter was true it will write
+ /// its label in the graph.
+ void writeLabel(std::ostream& os, const Node& item) const {
+ if (forceLabelMap) {
+ os << graph.id(item);
+ } else {
+ labelMap->write(os, item);
+ }
+ }
+
+ /// \brief Sorts the given node vector by label.
+ ///
+ /// Sorts the given node vector by label. If there was written an
+ /// "label" named map then the vector will be sorted by the values
+ /// of this map. Otherwise if the \c forceLabel parameter was true
+ /// it will be sorted by its id in the graph.
+ void sortByLabel(std::vector<Node>& nodes) const {
+ if (labelMap) {
+ labelMap->sort(nodes);
+ } else {
+ typedef IdMap<Graph, Node> Map;
+ Map map(graph);
+ _writer_bits::ComposeLess<Map> less(map);
+ std::sort(nodes.begin(), nodes.end(), less);
+ }
+ }
+
+ private:
+
+ typedef std::vector<std::pair<std::string, _writer_bits::
+ MapWriterBase<Node>*> > MapWriters;
+ MapWriters awriters, bwriters, writers;
+
+ _writer_bits::MapWriterBase<Node>* labelMap;
+ bool forceLabelMap;
+ bool forceSort;
+
+ const Graph& graph;
+ std::string name;
+
+ };
+
+ /// \ingroup section_io
/// \brief SectionWriter for writing a graph's edgesets.
///
/// The lemon format can store multiple graph edgesets with several maps.
More information about the Lemon-commits
mailing list