/* -*- C++ -*- * lemon/graph_writer.h - Part of LEMON, a generic C++ optimization library * * Copyright (C) 2005 Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport * (Egervary Research Group on Combinatorial Optimization, EGRES). * * Permission to use, modify and distribute this software is granted * provided that this copyright notice appears in all copies. For * precise terms see the accompanying LICENSE file. * * This software is provided "AS IS" with no warranty of any kind, * express or implied, and with no claim as to its suitability for any * purpose. * */ ///\ingroup io_group ///\file ///\brief Lemon Graph Format writer. /// #ifndef LEMON_GRAPH_WRITER_H #define LEMON_GRAPH_WRITER_H #include #include #include namespace lemon { /// \addtogroup io_group /// @{ /// \brief The graph writer class. /// /// The \c GraphWriter class provides the graph output. /// Before you read this documentation it might be useful to read the general /// description of \ref graph-io-page "Graph Input-Output". /// /// If you don't need very sophisticated /// behaviour then you can use the versions of the public function /// \ref writeGraph() to output a graph (or a max flow instance etc). /// /// To write a graph /// you should first give writing commands to the writer. You can declare /// write commands as \c NodeMap or \c EdgeMap writing and labeled Node and /// Edge writing. /// /// \code /// GraphWriter writer(std::cout, graph); /// \endcode /// /// The \c writeNodeMap() function declares a \c NodeMap writing /// command in the \c GraphWriter. You should give as parameter /// the name of the map and the map object. The NodeMap writing /// command with name "id" should write a unique map because it /// is regarded as ID map (such a map is essential if the graph has edges). /// /// \code /// IdMap nodeIdMap; /// writer.writeNodeMap("id", nodeIdMap); /// /// writer.writeNodeMap("coords", coords); /// writer.writeNodeMap("color", colorMap); /// \endcode /// /// With the \c writeEdgeMap() member function you can give an edge map /// writing command similar to the NodeMaps. /// /// \code /// DescriptorMap > /// edgeDescMap(graph); /// writer.writeEdgeMap("descriptor", edgeDescMap); /// /// writer.writeEdgeMap("weight", weightMap); /// writer.writeEdgeMap("label", labelMap); /// \endcode /// /// With \c writeNode() and \c writeEdge() functions you can /// point out Nodes and Edges in the graph. For example, you can /// write out the source and target of a maximum flow instance. /// /// \code /// writer.writeNode("source", sourceNode); /// writer.writeNode("target", targetNode); /// /// writer.writeEdge("observed", edge); /// \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 GraphReader /// \see \ref graph-io-page /// \author Balazs Dezso template class GraphWriter { public: typedef _Graph Graph; typedef typename Graph::Node Node; typedef typename Graph::Edge Edge; typedef _WriterTraits WriterTraits; /// \brief Construct a new GraphWriter. /// /// This function constructs a new GraphWriter to write the given graph /// to the given stream. GraphWriter(std::ostream& _os, const Graph& _graph) : writer(new LemonWriter(_os)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), edge_writer(*writer, edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new GraphWriter. /// /// This function constructs a new GraphWriter to write the given graph /// to the given file. GraphWriter(const std::string& _filename, const Graph& _graph) : writer(new LemonWriter(_filename)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), edge_writer(*writer, edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new GraphWriter. /// /// This function constructs a new GraphWriter to write the given graph /// to the given LemonReader. GraphWriter(LemonWriter& _writer, const Graph& _graph) : writer(_writer), own_writer(false), nodeset_writer(*writer, _graph, std::string()), edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), edge_writer(*writer, edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Destruct the graph writer. /// /// This function destructs the graph writer. ~GraphWriter() { if (own_writer) delete writer; } /// \brief Issue a new node map writing command for the writer. /// /// This function issues a new node map writing command to the writer. template GraphWriter& writeNodeMap(std::string name, const Map& map) { nodeset_writer.writeNodeMap(name, map); return *this; } /// \brief Issue a new node map writing command for the writer. /// /// This function issues a new node map writing command to the writer. template GraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { nodeset_writer.writeNodeMap(name, map, writer); return *this; } /// \brief Issue a new edge map writing command for the writer. /// /// This function issues a new edge map writing command to the writer. template GraphWriter& writeEdgeMap(std::string name, const Map& map) { edgeset_writer.writeEdgeMap(name, map); return *this; } /// \brief Issue a new edge map writing command for the writer. /// /// This function issues a new edge map writing command to the writer. template GraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { edgeset_writer.writeEdgeMap(name, map, writer); return *this; } /// \brief Issue a new labeled node writing command to the writer. /// /// This function issues a new labeled node writing command /// to the writer. GraphWriter& writeNode(std::string name, const Node& node) { node_writer.writeNode(name, node); return *this; } /// \brief Issue a new labeled edge writing command to the writer. /// /// This function issues a new labeled edge writing command /// to the writer. GraphWriter& writeEdge(std::string name, const Edge& edge) { edge_writer.writeEdge(name, edge); } /// \brief Issue a new attribute writing command. /// /// This function issues a new attribute writing command /// to the writer. template GraphWriter& writeAttribute(std::string name, const Value& value) { attribute_writer.writeAttribute(name, value); return *this; } /// \brief Issue a new attribute writing command. /// /// This function issues a new attribute writing command /// to the writer. template GraphWriter& writeAttribute(std::string name, const Value& value, const Writer& writer) { attribute_writer.writeAttribute(name, value, writer); 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. For more details see /// the \ref rwbackground "Background of Reading and Writing". operator LemonWriter&() { return *writer; } /// \brief Executes the writing commands. /// /// Executes the writing commands. void run() { writer->run(); } /// \brief Write the id of the given node. /// /// It writes the id of the given node. If there was written an "id" /// named node map then it will write the map value belonging to the node. void writeId(std::ostream& os, const Node& item) const { nodeset_writer.writeId(os, item); } /// \brief Write the id of the given edge. /// /// It writes the id of the given edge. If there was written an "id" /// named edge map then it will write the map value belonging to the edge. void writeId(std::ostream& os, const Edge& item) const { edgeset_writer.writeId(os, item); } private: LemonWriter* writer; bool own_writer; NodeSetWriter nodeset_writer; EdgeSetWriter edgeset_writer; NodeWriter node_writer; EdgeWriter edge_writer; AttributeWriter attribute_writer; }; ///\anchor writeGraph() /// /// \brief Write a graph to the output. /// /// Write a graph to the output. /// \param os The output stream. /// \param g The graph. template void writeGraph(std::ostream& os, const Graph &g) { GraphWriter writer(os, g); IdMap nodeIdMap(g); writer.writeNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); writer.writeEdgeMap("id", edgeIdMap); writer.run(); } /// \brief Write a capacitated graph instance to the output. /// /// Write a capacitated graph (graph+capacity on the /// edges) to the output. /// \param os The output stream. /// \param g The graph. /// \param capacity The capacity map. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity) { GraphWriter writer(os, g); IdMap nodeIdMap(g); writer.writeNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); writer.writeEdgeMap("id", edgeIdMap); writer.writeEdgeMap("capacity", capacity); writer.run(); } /// \brief Write a shortest path instance to the output. /// /// Write a shortest path instance (graph+capacity on the /// edges+designated source) to the output. /// \param os The output stream. /// \param g The graph. /// \param capacity The capacity map. /// \param s The source node. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s) { GraphWriter writer(os, g); IdMap nodeIdMap(g); writer.writeNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); writer.writeEdgeMap("id", edgeIdMap); writer.writeEdgeMap("capacity", capacity); writer.writeNode("source", s); writer.run(); } /// \brief Write a max flow instance to the output. /// /// Write a max flow instance (graph+capacity on the /// edges+designated source and target) to the output. /// /// \param os The output stream. /// \param g The graph. /// \param capacity The capacity map. /// \param s The source node. /// \param t The target node. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, const typename Graph::Node &t) { GraphWriter writer(os, g); IdMap nodeIdMap(g); writer.writeNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); writer.writeEdgeMap("id", edgeIdMap); writer.writeEdgeMap("capacity", capacity); writer.writeNode("source", s); writer.writeNode("target", t); writer.run(); } /// \brief Write a min cost flow instance to the output. /// /// Write a min cost flow instance (graph+capacity on the edges+cost /// function on the edges+designated source and target) to the output. /// /// \param os The output stream. /// \param g The graph. /// \param capacity The capacity map. /// \param s The source node. /// \param t The target node. /// \param cost The cost map. template void writeGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity, const typename Graph::Node &s, const typename Graph::Node &t, const CostMap& cost) { GraphWriter writer(os, g); IdMap nodeIdMap(g); writer.writeNodeMap("id", nodeIdMap); IdMap edgeIdMap(g); writer.writeEdgeMap("id", edgeIdMap); writer.writeEdgeMap("capacity", capacity); writer.writeEdgeMap("cost", cost); writer.writeNode("source", s); writer.writeNode("target", t); writer.run(); } /// \brief The undirected graph writer class. /// /// The \c UndirGraphWriter class provides the undir graph 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 UndirEdgeMap /// writing and labeled Node, Edge or UndirEdge writing. /// /// \code /// UndirGraphWriter writer(std::cout, graph); /// \endcode /// /// The \c writeNodeMap() function declares a \c NodeMap writing /// command in the \c UndirGraphWriter. You should give as parameter /// the name of the map and the map object. The NodeMap writing /// command with name "id" should write a unique map because it /// is regarded as ID map. /// /// \code /// IdMap nodeIdMap; /// writer.writeNodeMap("id", nodeIdMap); /// /// writer.writeNodeMap("coords", coords); /// writer.writeNodeMap("color", colorMap); /// \endcode /// /// With the \c writeUndirEdgeMap() member function you can give an /// undirected edge map writing command similar to the NodeMaps. /// /// \code /// DescriptorMap > /// edgeDescMap(graph); /// writer.writeUndirEdgeMap("descriptor", edgeDescMap); /// /// writer.writeUndirEdgeMap("weight", weightMap); /// writer.writeUndirEdgeMap("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 writeUndirEdge() 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.writeUndirEdge("observed", undirEdge); /// \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 class UndirGraphWriter { public: typedef _Graph Graph; typedef typename Graph::Node Node; typedef typename Graph::Edge Edge; typedef typename Graph::UndirEdge UndirEdge; typedef _WriterTraits WriterTraits; /// \brief Construct a new UndirGraphWriter. /// /// Construct a new UndirGraphWriter. It writes the given graph /// to the given stream. UndirGraphWriter(std::ostream& _os, const Graph& _graph) : writer(new LemonWriter(_os)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), undir_edge_writer(*writer, undir_edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new UndirGraphWriter. /// /// Construct a new UndirGraphWriter. It writes the given graph /// to the given file. UndirGraphWriter(const std::string& _filename, const Graph& _graph) : writer(new LemonWriter(_filename)), own_writer(true), nodeset_writer(*writer, _graph, std::string()), undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), undir_edge_writer(*writer, undir_edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Construct a new UndirGraphWriter. /// /// Construct a new UndirGraphWriter. It writes the given graph /// to given LemonReader. UndirGraphWriter(LemonWriter& _writer, const Graph& _graph) : writer(_writer), own_writer(false), nodeset_writer(*writer, _graph, std::string()), undir_edgeset_writer(*writer, _graph, nodeset_writer, std::string()), node_writer(*writer, nodeset_writer, std::string()), undir_edge_writer(*writer, undir_edgeset_writer, std::string()), attribute_writer(*writer, std::string()) {} /// \brief Destruct the graph writer. /// /// Destruct the graph writer. ~UndirGraphWriter() { if (own_writer) delete writer; } /// \brief Issue a new node map writing command to the writer. /// /// This function issues a new node map writing command to the writer. template UndirGraphWriter& writeNodeMap(std::string name, const Map& map) { nodeset_writer.writeNodeMap(name, map); return *this; } /// \brief Issue a new node map writing command to the writer. /// /// This function issues a new node map writing command to the writer. template UndirGraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { nodeset_writer.writeNodeMap(name, map, writer); return *this; } /// \brief Issue a new edge map writing command to the writer. /// /// This function issues a new edge map writing command to the writer. template UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { undir_edgeset_writer.writeEdgeMap(name, map); return *this; } /// \brief Issue a new edge map writing command to the writer. /// /// This function issues a new edge map writing command to the writer. template UndirGraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { undir_edgeset_writer.writeEdgeMap(name, map, writer); return *this; } /// \brief Issue a new undirected edge map writing command to the writer. /// /// This function issues a new undirected edge map writing /// command to the writer. template UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { undir_edgeset_writer.writeUndirEdgeMap(name, map); return *this; } /// \brief Issue a new undirected edge map writing command to the writer. /// /// This function issues a new undirected edge map writing /// command to the writer. template UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { undir_edgeset_writer.writeUndirEdgeMap(name, map, writer); return *this; } /// \brief Issue a new labeled node writer to the writer. /// /// This function issues a new labeled node writing /// command to the writer. UndirGraphWriter& writeNode(std::string name, const Node& node) { node_writer.writeNode(name, node); return *this; } /// \brief Issue a new labeled edge writer to the writer. /// /// This function issues a new labeled edge writing /// command to the writer. UndirGraphWriter& writeEdge(std::string name, const Edge& edge) { undir_edge_writer.writeEdge(name, edge); } /// \brief Issue a new labeled undirected edge writing command to /// the writer. /// /// Issue a new labeled undirected edge writing command to /// the writer. UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) { undir_edge_writer.writeUndirEdge(name, edge); } /// \brief Issue a new attribute writing command. /// /// This function issues a new attribute writing /// command to the writer. template UndirGraphWriter& writeAttribute(std::string name, const Value& value) { attribute_writer.writeAttribute(name, value); return *this; } /// \brief Issue a new attribute writing command. /// /// This function issues a new attribute writing /// command to the writer. template UndirGraphWriter& writeAttribute(std::string name, const Value& value, const Writer& writer) { attribute_writer.writeAttribute(name, value, writer); 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 Write the id of the given node. /// /// It writes the id of the given node. If there was written an "id" /// named node map then it will write the map value belonging to the node. void writeId(std::ostream& os, const Node& item) const { nodeset_writer.writeId(os, item); } /// \brief Write the id of the given edge. /// /// It writes the id of the given edge. If there was written an "id" /// named edge map then it will write the map value belonging to the edge. void writeId(std::ostream& os, const Edge& item) const { undir_edgeset_writer.writeId(os, item); } /// \brief Write the id of the given undirected edge. /// /// It writes the id of the given undirected edge. If there was written /// an "id" named edge map then it will write the map value belonging to /// the edge. void writeId(std::ostream& os, const UndirEdge& item) const { undir_edgeset_writer.writeId(os, item); } private: LemonWriter* writer; bool own_writer; NodeSetWriter nodeset_writer; UndirEdgeSetWriter undir_edgeset_writer; NodeWriter node_writer; UndirEdgeWriter undir_edge_writer; AttributeWriter attribute_writer; }; /// \brief Write an undirected graph to the output. /// /// Write an undirected graph to the output. /// \param os The output stream. /// \param g The graph. template void writeUndirGraph(std::ostream& os, const Graph &g) { UndirGraphWriter writer(os, g); writer.run(); } /// \brief Write an undirected multigraph (undirected graph + capacity /// map on the edges) to the output. /// /// Write an undirected multigraph (undirected graph + capacity /// map on the edges) to the output. /// \param os The output stream. /// \param g The graph. /// \param capacity The capacity undirected map. template void writeUndirGraph(std::ostream& os, const Graph &g, const CapacityMap& capacity) { UndirGraphWriter writer(os, g); writer.writeUndirEdgeMap("capacity", capacity); writer.run(); } /// @} } #endif