/* -*- 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. To write a graph /// you should first give writing commands for the writer. You can declare /// write command 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. /// /// \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. By example, you can /// write out the source and target of the graph. /// /// \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 execute all the writer 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. /// /// Construct a new GraphWriter. It writes 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. /// /// Construct a new GraphWriter. It writes into 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. /// /// Construct a new GraphWriter. It writes into the given graph /// to 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. /// /// Destruct the graph writer. ~GraphWriter() { if (own_writer) delete writer; } /// \brief Add a new node map writer command for the writer. /// /// Add a new node map writer command for the writer. template GraphWriter& writeNodeMap(std::string name, const Map& map) { nodeset_writer.writeNodeMap(name, map); return *this; } /// \brief Add a new node map writer command for the writer. /// /// Add a new node map writer command for the writer. template GraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { nodeset_writer.writeNodeMap(name, map, writer); return *this; } /// \brief Add a new edge map writer command for the writer. /// /// Add a new edge map writer command for the writer. template GraphWriter& writeEdgeMap(std::string name, const Map& map) { edgeset_writer.writeEdgeMap(name, map); return *this; } /// \brief Add a new edge map writer command for the writer. /// /// Add a new edge map writer command for the writer. template GraphWriter& writeEdgeMap(std::string name, const Map& map, const Writer& writer = Writer()) { edgeset_writer.writeEdgeMap(name, map, writer); return *this; } /// \brief Add a new labeled node writer for the writer. /// /// Add a new labeled node writer for the writer. GraphWriter& writeNode(std::string name, const Node& node) { node_writer.writeNode(name, node); return *this; } /// \brief Add a new labeled edge writer for the writer. /// /// Add a new labeled edge writer for the writer. GraphWriter& writeEdge(std::string name, const Edge& edge) { edge_writer.writeEdge(name, edge); } /// \brief Add a new attribute writer command. /// /// Add a new attribute writer command. template GraphWriter& writeAttribute(std::string name, const Value& value) { attribute_writer.writeAttribute(name, value); return *this; } /// \brief Add a new attribute writer command. /// /// Add a new attribute writer command. 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 make 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 writer commands. /// /// Executes the writer 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 belongs 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 belongs 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; }; /// \brief Write a graph to the output. /// /// Write a graph 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 Write a graph to the output. /// /// Write a graph 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 graph to the output. /// /// Write a graph 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 graph to the output. /// /// Write a graph 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 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 The undirected graph writer class. /// /// The \c UndirGraphWriter class provides the undir graph output. To write /// a graph you should first give writing commands for 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 /// point out nodes and undirected edges in the graph. By 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 execute all the writer 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 into 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 into 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 Add a new node map writer command for the writer. /// /// Add a new node map writer command for the writer. template UndirGraphWriter& writeNodeMap(std::string name, const Map& map) { nodeset_writer.writeNodeMap(name, map); return *this; } /// \brief Add a new node map writer command for the writer. /// /// Add a new node map writer command for the writer. template UndirGraphWriter& writeNodeMap(std::string name, const Map& map, const Writer& writer = Writer()) { nodeset_writer.writeNodeMap(name, map, writer); return *this; } /// \brief Add a new edge map writer command for the writer. /// /// Add a new edge map writer command for the writer. template UndirGraphWriter& writeEdgeMap(std::string name, const Map& map) { undir_edgeset_writer.writeEdgeMap(name, map); return *this; } /// \brief Add a new edge map writer command for the writer. /// /// Add a new edge map writer command for 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 Add a new undirected edge map writer command for the writer. /// /// Add a new undirected edge map writer command for the writer. template UndirGraphWriter& writeUndirEdgeMap(std::string name, const Map& map) { undir_edgeset_writer.writeUndirEdgeMap(name, map); return *this; } /// \brief Add a new undirected edge map writer command for the writer. /// /// Add a new edge undirected map writer command for 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 Add a new labeled node writer for the writer. /// /// Add a new labeled node writer for the writer. UndirGraphWriter& writeNode(std::string name, const Node& node) { node_writer.writeNode(name, node); return *this; } /// \brief Add a new labeled edge writer for the writer. /// /// Add a new labeled edge writer for the writer. UndirGraphWriter& writeEdge(std::string name, const Edge& edge) { undir_edge_writer.writeEdge(name, edge); } /// \brief Add a new labeled undirected edge writer for the writer. /// /// Add a new labeled undirected edge writer for the writer. UndirGraphWriter& writeUndirEdge(std::string name, const UndirEdge& edge) { undir_edge_writer.writeUndirEdge(name, edge); } /// \brief Add a new attribute writer command. /// /// Add a new attribute writer command. template UndirGraphWriter& writeAttribute(std::string name, const Value& value) { attribute_writer.writeAttribute(name, value); return *this; } /// \brief Add a new attribute writer command. /// /// Add a new attribute writer command. 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 make 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 writer commands. /// /// Executes the writer 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 belongs 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 belongs 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 belongs 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. /// \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(); } /// \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(); } /// @} } #endif