lemon/lgf_writer.h
changeset 1024 b84e68af8248
parent 877 141f9c0db4a3
child 1026 699c7eac2c6d
equal deleted inserted replaced
33:c9d004303b79 34:28bd1197eef9
   984   template <typename TGR>
   984   template <typename TGR>
   985   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
   985   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn);
   986 
   986 
   987   /// \ingroup lemon_io
   987   /// \ingroup lemon_io
   988   ///
   988   ///
   989   /// \brief \ref lgf-format "LGF" writer for directed graphs
   989   /// \brief \ref lgf-format "LGF" writer for undirected graphs
   990   ///
   990   ///
   991   /// This utility writes an \ref lgf-format "LGF" file.
   991   /// This utility writes an \ref lgf-format "LGF" file.
   992   ///
   992   ///
   993   /// It can be used almost the same way as \c DigraphWriter.
   993   /// It can be used almost the same way as \c DigraphWriter.
   994   /// The only difference is that this class can handle edges and
   994   /// The only difference is that this class can handle edges and
  1040 
  1040 
  1041   public:
  1041   public:
  1042 
  1042 
  1043     /// \brief Constructor
  1043     /// \brief Constructor
  1044     ///
  1044     ///
  1045     /// Construct a directed graph writer, which writes to the given
  1045     /// Construct an undirected graph writer, which writes to the
  1046     /// output stream.
  1046     /// given output stream.
  1047     GraphWriter(const GR& graph, std::ostream& os = std::cout)
  1047     GraphWriter(const GR& graph, std::ostream& os = std::cout)
  1048       : _os(&os), local_os(false), _graph(graph),
  1048       : _os(&os), local_os(false), _graph(graph),
  1049         _skip_nodes(false), _skip_edges(false) {}
  1049         _skip_nodes(false), _skip_edges(false) {}
  1050 
  1050 
  1051     /// \brief Constructor
  1051     /// \brief Constructor
  1052     ///
  1052     ///
  1053     /// Construct a directed graph writer, which writes to the given
  1053     /// Construct a undirected graph writer, which writes to the given
  1054     /// output file.
  1054     /// output file.
  1055     GraphWriter(const GR& graph, const std::string& fn)
  1055     GraphWriter(const GR& graph, const std::string& fn)
  1056       : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
  1056       : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
  1057         _skip_nodes(false), _skip_edges(false) {
  1057         _skip_nodes(false), _skip_edges(false) {
  1058       if (!(*_os)) {
  1058       if (!(*_os)) {
  1061       }
  1061       }
  1062     }
  1062     }
  1063 
  1063 
  1064     /// \brief Constructor
  1064     /// \brief Constructor
  1065     ///
  1065     ///
  1066     /// Construct a directed graph writer, which writes to the given
  1066     /// Construct a undirected graph writer, which writes to the given
  1067     /// output file.
  1067     /// output file.
  1068     GraphWriter(const GR& graph, const char* fn)
  1068     GraphWriter(const GR& graph, const char* fn)
  1069       : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
  1069       : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
  1070         _skip_nodes(false), _skip_edges(false) {
  1070         _skip_nodes(false), _skip_edges(false) {
  1071       if (!(*_os)) {
  1071       if (!(*_os)) {
  1287     GraphWriter& nodes(const std::string& caption) {
  1287     GraphWriter& nodes(const std::string& caption) {
  1288       _nodes_caption = caption;
  1288       _nodes_caption = caption;
  1289       return *this;
  1289       return *this;
  1290     }
  1290     }
  1291 
  1291 
  1292     /// \brief Add an additional caption to the \c \@arcs section
  1292     /// \brief Add an additional caption to the \c \@edges section
  1293     ///
  1293     ///
  1294     /// Add an additional caption to the \c \@arcs section.
  1294     /// Add an additional caption to the \c \@edges section.
  1295     GraphWriter& edges(const std::string& caption) {
  1295     GraphWriter& edges(const std::string& caption) {
  1296       _edges_caption = caption;
  1296       _edges_caption = caption;
  1297       return *this;
  1297       return *this;
  1298     }
  1298     }
  1299 
  1299 
  1603   /// \relates GraphWriter
  1603   /// \relates GraphWriter
  1604   /// \sa graphWriter(const TGR& graph, std::ostream& os)
  1604   /// \sa graphWriter(const TGR& graph, std::ostream& os)
  1605   template <typename TGR>
  1605   template <typename TGR>
  1606   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
  1606   GraphWriter<TGR> graphWriter(const TGR& graph, const char* fn) {
  1607     GraphWriter<TGR> tmp(graph, fn);
  1607     GraphWriter<TGR> tmp(graph, fn);
       
  1608     return tmp;
       
  1609   }
       
  1610 
       
  1611   template <typename BGR>
       
  1612   class BpGraphWriter;
       
  1613 
       
  1614   template <typename TBGR>
       
  1615   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
       
  1616                                     std::ostream& os = std::cout);
       
  1617   template <typename TBGR>
       
  1618   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
       
  1619   template <typename TBGR>
       
  1620   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
       
  1621 
       
  1622   /// \ingroup lemon_io
       
  1623   ///
       
  1624   /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
       
  1625   ///
       
  1626   /// This utility writes an \ref lgf-format "LGF" file.
       
  1627   ///
       
  1628   /// It can be used almost the same way as \c GraphWriter, but it
       
  1629   /// reads the red and blue nodes from separate sections, and these
       
  1630   /// sections can contain different set of maps.
       
  1631   ///
       
  1632   /// The red and blue maps are written to the corresponding
       
  1633   /// sections. The node maps are written to both of these sections
       
  1634   /// with the same map name.
       
  1635   template <typename BGR>
       
  1636   class BpGraphWriter {
       
  1637   public:
       
  1638 
       
  1639     typedef BGR BpGraph;
       
  1640     TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
       
  1641 
       
  1642   private:
       
  1643 
       
  1644 
       
  1645     std::ostream* _os;
       
  1646     bool local_os;
       
  1647 
       
  1648     const BGR& _graph;
       
  1649 
       
  1650     std::string _nodes_caption;
       
  1651     std::string _edges_caption;
       
  1652     std::string _attributes_caption;
       
  1653 
       
  1654     typedef std::map<Node, std::string> NodeIndex;
       
  1655     NodeIndex _node_index;
       
  1656     typedef std::map<Edge, std::string> EdgeIndex;
       
  1657     EdgeIndex _edge_index;
       
  1658 
       
  1659     typedef std::vector<std::pair<std::string,
       
  1660       _writer_bits::MapStorageBase<Node>* > > NodeMaps;
       
  1661     NodeMaps _red_maps;
       
  1662     NodeMaps _blue_maps;
       
  1663 
       
  1664     typedef std::vector<std::pair<std::string,
       
  1665       _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
       
  1666     EdgeMaps _edge_maps;
       
  1667 
       
  1668     typedef std::vector<std::pair<std::string,
       
  1669       _writer_bits::ValueStorageBase*> > Attributes;
       
  1670     Attributes _attributes;
       
  1671 
       
  1672     bool _skip_nodes;
       
  1673     bool _skip_edges;
       
  1674 
       
  1675   public:
       
  1676 
       
  1677     /// \brief Constructor
       
  1678     ///
       
  1679     /// Construct a bipartite graph writer, which writes to the given
       
  1680     /// output stream.
       
  1681     BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
       
  1682       : _os(&os), local_os(false), _graph(graph),
       
  1683         _skip_nodes(false), _skip_edges(false) {}
       
  1684 
       
  1685     /// \brief Constructor
       
  1686     ///
       
  1687     /// Construct a bipartite graph writer, which writes to the given
       
  1688     /// output file.
       
  1689     BpGraphWriter(const BGR& graph, const std::string& fn)
       
  1690       : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
       
  1691         _skip_nodes(false), _skip_edges(false) {
       
  1692       if (!(*_os)) {
       
  1693         delete _os;
       
  1694         throw IoError("Cannot write file", fn);
       
  1695       }
       
  1696     }
       
  1697 
       
  1698     /// \brief Constructor
       
  1699     ///
       
  1700     /// Construct a bipartite graph writer, which writes to the given
       
  1701     /// output file.
       
  1702     BpGraphWriter(const BGR& graph, const char* fn)
       
  1703       : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
       
  1704         _skip_nodes(false), _skip_edges(false) {
       
  1705       if (!(*_os)) {
       
  1706         delete _os;
       
  1707         throw IoError("Cannot write file", fn);
       
  1708       }
       
  1709     }
       
  1710 
       
  1711     /// \brief Destructor
       
  1712     ~BpGraphWriter() {
       
  1713       for (typename NodeMaps::iterator it = _red_maps.begin();
       
  1714            it != _red_maps.end(); ++it) {
       
  1715         delete it->second;
       
  1716       }
       
  1717 
       
  1718       for (typename NodeMaps::iterator it = _blue_maps.begin();
       
  1719            it != _blue_maps.end(); ++it) {
       
  1720         delete it->second;
       
  1721       }
       
  1722 
       
  1723       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  1724            it != _edge_maps.end(); ++it) {
       
  1725         delete it->second;
       
  1726       }
       
  1727 
       
  1728       for (typename Attributes::iterator it = _attributes.begin();
       
  1729            it != _attributes.end(); ++it) {
       
  1730         delete it->second;
       
  1731       }
       
  1732 
       
  1733       if (local_os) {
       
  1734         delete _os;
       
  1735       }
       
  1736     }
       
  1737 
       
  1738   private:
       
  1739 
       
  1740     template <typename TBGR>
       
  1741     friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
       
  1742                                              std::ostream& os);
       
  1743     template <typename TBGR>
       
  1744     friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
       
  1745                                              const std::string& fn);
       
  1746     template <typename TBGR>
       
  1747     friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
       
  1748 
       
  1749     BpGraphWriter(BpGraphWriter& other)
       
  1750       : _os(other._os), local_os(other.local_os), _graph(other._graph),
       
  1751         _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
       
  1752 
       
  1753       other._os = 0;
       
  1754       other.local_os = false;
       
  1755 
       
  1756       _node_index.swap(other._node_index);
       
  1757       _edge_index.swap(other._edge_index);
       
  1758 
       
  1759       _red_maps.swap(other._red_maps);
       
  1760       _blue_maps.swap(other._blue_maps);
       
  1761       _edge_maps.swap(other._edge_maps);
       
  1762       _attributes.swap(other._attributes);
       
  1763 
       
  1764       _nodes_caption = other._nodes_caption;
       
  1765       _edges_caption = other._edges_caption;
       
  1766       _attributes_caption = other._attributes_caption;
       
  1767     }
       
  1768 
       
  1769     BpGraphWriter& operator=(const BpGraphWriter&);
       
  1770 
       
  1771   public:
       
  1772 
       
  1773     /// \name Writing Rules
       
  1774     /// @{
       
  1775 
       
  1776     /// \brief Node map writing rule
       
  1777     ///
       
  1778     /// Add a node map writing rule to the writer.
       
  1779     template <typename Map>
       
  1780     BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
       
  1781       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1782       _writer_bits::MapStorageBase<Node>* red_storage =
       
  1783         new _writer_bits::MapStorage<Node, Map>(map);
       
  1784       _red_maps.push_back(std::make_pair(caption, red_storage));
       
  1785       _writer_bits::MapStorageBase<Node>* blue_storage =
       
  1786         new _writer_bits::MapStorage<Node, Map>(map);
       
  1787       _blue_maps.push_back(std::make_pair(caption, blue_storage));
       
  1788       return *this;
       
  1789     }
       
  1790 
       
  1791     /// \brief Node map writing rule
       
  1792     ///
       
  1793     /// Add a node map writing rule with specialized converter to the
       
  1794     /// writer.
       
  1795     template <typename Map, typename Converter>
       
  1796     BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
       
  1797                            const Converter& converter = Converter()) {
       
  1798       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1799       _writer_bits::MapStorageBase<Node>* red_storage =
       
  1800         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
       
  1801       _red_maps.push_back(std::make_pair(caption, red_storage));
       
  1802       _writer_bits::MapStorageBase<Node>* blue_storage =
       
  1803         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
       
  1804       _blue_maps.push_back(std::make_pair(caption, blue_storage));
       
  1805       return *this;
       
  1806     }
       
  1807 
       
  1808     /// \brief Red map writing rule
       
  1809     ///
       
  1810     /// Add a red map writing rule to the writer.
       
  1811     template <typename Map>
       
  1812     BpGraphWriter& redMap(const std::string& caption, const Map& map) {
       
  1813       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1814       _writer_bits::MapStorageBase<Node>* storage =
       
  1815         new _writer_bits::MapStorage<Node, Map>(map);
       
  1816       _red_maps.push_back(std::make_pair(caption, storage));
       
  1817       return *this;
       
  1818     }
       
  1819 
       
  1820     /// \brief Red map writing rule
       
  1821     ///
       
  1822     /// Add a red map writing rule with specialized converter to the
       
  1823     /// writer.
       
  1824     template <typename Map, typename Converter>
       
  1825     BpGraphWriter& redMap(const std::string& caption, const Map& map,
       
  1826                           const Converter& converter = Converter()) {
       
  1827       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1828       _writer_bits::MapStorageBase<Node>* storage =
       
  1829         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
       
  1830       _red_maps.push_back(std::make_pair(caption, storage));
       
  1831       return *this;
       
  1832     }
       
  1833 
       
  1834     /// \brief Blue map writing rule
       
  1835     ///
       
  1836     /// Add a blue map writing rule to the writer.
       
  1837     template <typename Map>
       
  1838     BpGraphWriter& blueMap(const std::string& caption, const Map& map) {
       
  1839       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1840       _writer_bits::MapStorageBase<Node>* storage =
       
  1841         new _writer_bits::MapStorage<Node, Map>(map);
       
  1842       _blue_maps.push_back(std::make_pair(caption, storage));
       
  1843       return *this;
       
  1844     }
       
  1845 
       
  1846     /// \brief Blue map writing rule
       
  1847     ///
       
  1848     /// Add a blue map writing rule with specialized converter to the
       
  1849     /// writer.
       
  1850     template <typename Map, typename Converter>
       
  1851     BpGraphWriter& blueMap(const std::string& caption, const Map& map,
       
  1852                            const Converter& converter = Converter()) {
       
  1853       checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
       
  1854       _writer_bits::MapStorageBase<Node>* storage =
       
  1855         new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
       
  1856       _blue_maps.push_back(std::make_pair(caption, storage));
       
  1857       return *this;
       
  1858     }
       
  1859 
       
  1860     /// \brief Edge map writing rule
       
  1861     ///
       
  1862     /// Add an edge map writing rule to the writer.
       
  1863     template <typename Map>
       
  1864     BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
       
  1865       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
       
  1866       _writer_bits::MapStorageBase<Edge>* storage =
       
  1867         new _writer_bits::MapStorage<Edge, Map>(map);
       
  1868       _edge_maps.push_back(std::make_pair(caption, storage));
       
  1869       return *this;
       
  1870     }
       
  1871 
       
  1872     /// \brief Edge map writing rule
       
  1873     ///
       
  1874     /// Add an edge map writing rule with specialized converter to the
       
  1875     /// writer.
       
  1876     template <typename Map, typename Converter>
       
  1877     BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
       
  1878                           const Converter& converter = Converter()) {
       
  1879       checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
       
  1880       _writer_bits::MapStorageBase<Edge>* storage =
       
  1881         new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
       
  1882       _edge_maps.push_back(std::make_pair(caption, storage));
       
  1883       return *this;
       
  1884     }
       
  1885 
       
  1886     /// \brief Arc map writing rule
       
  1887     ///
       
  1888     /// Add an arc map writing rule to the writer.
       
  1889     template <typename Map>
       
  1890     BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
       
  1891       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
       
  1892       _writer_bits::MapStorageBase<Edge>* forward_storage =
       
  1893         new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
       
  1894       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
       
  1895       _writer_bits::MapStorageBase<Edge>* backward_storage =
       
  1896         new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
       
  1897       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
       
  1898       return *this;
       
  1899     }
       
  1900 
       
  1901     /// \brief Arc map writing rule
       
  1902     ///
       
  1903     /// Add an arc map writing rule with specialized converter to the
       
  1904     /// writer.
       
  1905     template <typename Map, typename Converter>
       
  1906     BpGraphWriter& arcMap(const std::string& caption, const Map& map,
       
  1907                           const Converter& converter = Converter()) {
       
  1908       checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
       
  1909       _writer_bits::MapStorageBase<Edge>* forward_storage =
       
  1910         new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
       
  1911         (_graph, map, converter);
       
  1912       _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
       
  1913       _writer_bits::MapStorageBase<Edge>* backward_storage =
       
  1914         new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
       
  1915         (_graph, map, converter);
       
  1916       _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
       
  1917       return *this;
       
  1918     }
       
  1919 
       
  1920     /// \brief Attribute writing rule
       
  1921     ///
       
  1922     /// Add an attribute writing rule to the writer.
       
  1923     template <typename Value>
       
  1924     BpGraphWriter& attribute(const std::string& caption, const Value& value) {
       
  1925       _writer_bits::ValueStorageBase* storage =
       
  1926         new _writer_bits::ValueStorage<Value>(value);
       
  1927       _attributes.push_back(std::make_pair(caption, storage));
       
  1928       return *this;
       
  1929     }
       
  1930 
       
  1931     /// \brief Attribute writing rule
       
  1932     ///
       
  1933     /// Add an attribute writing rule with specialized converter to the
       
  1934     /// writer.
       
  1935     template <typename Value, typename Converter>
       
  1936     BpGraphWriter& attribute(const std::string& caption, const Value& value,
       
  1937                              const Converter& converter = Converter()) {
       
  1938       _writer_bits::ValueStorageBase* storage =
       
  1939         new _writer_bits::ValueStorage<Value, Converter>(value, converter);
       
  1940       _attributes.push_back(std::make_pair(caption, storage));
       
  1941       return *this;
       
  1942     }
       
  1943 
       
  1944     /// \brief Node writing rule
       
  1945     ///
       
  1946     /// Add a node writing rule to the writer.
       
  1947     BpGraphWriter& node(const std::string& caption, const Node& node) {
       
  1948       typedef _writer_bits::MapLookUpConverter<Node> Converter;
       
  1949       Converter converter(_node_index);
       
  1950       _writer_bits::ValueStorageBase* storage =
       
  1951         new _writer_bits::ValueStorage<Node, Converter>(node, converter);
       
  1952       _attributes.push_back(std::make_pair(caption, storage));
       
  1953       return *this;
       
  1954     }
       
  1955 
       
  1956     /// \brief Edge writing rule
       
  1957     ///
       
  1958     /// Add an edge writing rule to writer.
       
  1959     BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
       
  1960       typedef _writer_bits::MapLookUpConverter<Edge> Converter;
       
  1961       Converter converter(_edge_index);
       
  1962       _writer_bits::ValueStorageBase* storage =
       
  1963         new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
       
  1964       _attributes.push_back(std::make_pair(caption, storage));
       
  1965       return *this;
       
  1966     }
       
  1967 
       
  1968     /// \brief Arc writing rule
       
  1969     ///
       
  1970     /// Add an arc writing rule to writer.
       
  1971     BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
       
  1972       typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
       
  1973       Converter converter(_graph, _edge_index);
       
  1974       _writer_bits::ValueStorageBase* storage =
       
  1975         new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
       
  1976       _attributes.push_back(std::make_pair(caption, storage));
       
  1977       return *this;
       
  1978     }
       
  1979 
       
  1980     /// \name Section Captions
       
  1981     /// @{
       
  1982 
       
  1983     /// \brief Add an additional caption to the \c \@red_nodes and
       
  1984     /// \c \@blue_nodes section
       
  1985     ///
       
  1986     /// Add an additional caption to the \c \@red_nodes and \c
       
  1987     /// \@blue_nodes section.
       
  1988     BpGraphWriter& nodes(const std::string& caption) {
       
  1989       _nodes_caption = caption;
       
  1990       return *this;
       
  1991     }
       
  1992 
       
  1993     /// \brief Add an additional caption to the \c \@edges section
       
  1994     ///
       
  1995     /// Add an additional caption to the \c \@edges section.
       
  1996     BpGraphWriter& edges(const std::string& caption) {
       
  1997       _edges_caption = caption;
       
  1998       return *this;
       
  1999     }
       
  2000 
       
  2001     /// \brief Add an additional caption to the \c \@attributes section
       
  2002     ///
       
  2003     /// Add an additional caption to the \c \@attributes section.
       
  2004     BpGraphWriter& attributes(const std::string& caption) {
       
  2005       _attributes_caption = caption;
       
  2006       return *this;
       
  2007     }
       
  2008 
       
  2009     /// \name Skipping Section
       
  2010     /// @{
       
  2011 
       
  2012     /// \brief Skip writing the node set
       
  2013     ///
       
  2014     /// The \c \@red_nodes and \c \@blue_nodes section will not be
       
  2015     /// written to the stream.
       
  2016     BpGraphWriter& skipNodes() {
       
  2017       LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
       
  2018       _skip_nodes = true;
       
  2019       return *this;
       
  2020     }
       
  2021 
       
  2022     /// \brief Skip writing edge set
       
  2023     ///
       
  2024     /// The \c \@edges section will not be written to the stream.
       
  2025     BpGraphWriter& skipEdges() {
       
  2026       LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
       
  2027       _skip_edges = true;
       
  2028       return *this;
       
  2029     }
       
  2030 
       
  2031     /// @}
       
  2032 
       
  2033   private:
       
  2034 
       
  2035     void writeRedNodes() {
       
  2036       _writer_bits::MapStorageBase<Node>* label = 0;
       
  2037       for (typename NodeMaps::iterator it = _red_maps.begin();
       
  2038            it != _red_maps.end(); ++it) {
       
  2039         if (it->first == "label") {
       
  2040           label = it->second;
       
  2041           break;
       
  2042         }
       
  2043       }
       
  2044 
       
  2045       *_os << "@red_nodes";
       
  2046       if (!_nodes_caption.empty()) {
       
  2047         _writer_bits::writeToken(*_os << ' ', _nodes_caption);
       
  2048       }
       
  2049       *_os << std::endl;
       
  2050 
       
  2051       if (label == 0) {
       
  2052         *_os << "label" << '\t';
       
  2053       }
       
  2054       for (typename NodeMaps::iterator it = _red_maps.begin();
       
  2055            it != _red_maps.end(); ++it) {
       
  2056         _writer_bits::writeToken(*_os, it->first) << '\t';
       
  2057       }
       
  2058       *_os << std::endl;
       
  2059 
       
  2060       std::vector<Node> nodes;
       
  2061       for (RedIt n(_graph); n != INVALID; ++n) {
       
  2062         nodes.push_back(n);
       
  2063       }
       
  2064 
       
  2065       if (label == 0) {
       
  2066         IdMap<BGR, Node> id_map(_graph);
       
  2067         _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
       
  2068         std::sort(nodes.begin(), nodes.end(), id_less);
       
  2069       } else {
       
  2070         label->sort(nodes);
       
  2071       }
       
  2072 
       
  2073       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
       
  2074         Node n = nodes[i];
       
  2075         if (label == 0) {
       
  2076           std::ostringstream os;
       
  2077           os << _graph.id(n);
       
  2078           _writer_bits::writeToken(*_os, os.str());
       
  2079           *_os << '\t';
       
  2080           _node_index.insert(std::make_pair(n, os.str()));
       
  2081         }
       
  2082         for (typename NodeMaps::iterator it = _red_maps.begin();
       
  2083              it != _red_maps.end(); ++it) {
       
  2084           std::string value = it->second->get(n);
       
  2085           _writer_bits::writeToken(*_os, value);
       
  2086           if (it->first == "label") {
       
  2087             _node_index.insert(std::make_pair(n, value));
       
  2088           }
       
  2089           *_os << '\t';
       
  2090         }
       
  2091         *_os << std::endl;
       
  2092       }
       
  2093     }
       
  2094 
       
  2095     void writeBlueNodes() {
       
  2096       _writer_bits::MapStorageBase<Node>* label = 0;
       
  2097       for (typename NodeMaps::iterator it = _blue_maps.begin();
       
  2098            it != _blue_maps.end(); ++it) {
       
  2099         if (it->first == "label") {
       
  2100           label = it->second;
       
  2101           break;
       
  2102         }
       
  2103       }
       
  2104 
       
  2105       *_os << "@blue_nodes";
       
  2106       if (!_nodes_caption.empty()) {
       
  2107         _writer_bits::writeToken(*_os << ' ', _nodes_caption);
       
  2108       }
       
  2109       *_os << std::endl;
       
  2110 
       
  2111       if (label == 0) {
       
  2112         *_os << "label" << '\t';
       
  2113       }
       
  2114       for (typename NodeMaps::iterator it = _blue_maps.begin();
       
  2115            it != _blue_maps.end(); ++it) {
       
  2116         _writer_bits::writeToken(*_os, it->first) << '\t';
       
  2117       }
       
  2118       *_os << std::endl;
       
  2119 
       
  2120       std::vector<Node> nodes;
       
  2121       for (BlueIt n(_graph); n != INVALID; ++n) {
       
  2122         nodes.push_back(n);
       
  2123       }
       
  2124 
       
  2125       if (label == 0) {
       
  2126         IdMap<BGR, Node> id_map(_graph);
       
  2127         _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
       
  2128         std::sort(nodes.begin(), nodes.end(), id_less);
       
  2129       } else {
       
  2130         label->sort(nodes);
       
  2131       }
       
  2132 
       
  2133       for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
       
  2134         Node n = nodes[i];
       
  2135         if (label == 0) {
       
  2136           std::ostringstream os;
       
  2137           os << _graph.id(n);
       
  2138           _writer_bits::writeToken(*_os, os.str());
       
  2139           *_os << '\t';
       
  2140           _node_index.insert(std::make_pair(n, os.str()));
       
  2141         }
       
  2142         for (typename NodeMaps::iterator it = _blue_maps.begin();
       
  2143              it != _blue_maps.end(); ++it) {
       
  2144           std::string value = it->second->get(n);
       
  2145           _writer_bits::writeToken(*_os, value);
       
  2146           if (it->first == "label") {
       
  2147             _node_index.insert(std::make_pair(n, value));
       
  2148           }
       
  2149           *_os << '\t';
       
  2150         }
       
  2151         *_os << std::endl;
       
  2152       }
       
  2153     }
       
  2154 
       
  2155     void createRedNodeIndex() {
       
  2156       _writer_bits::MapStorageBase<Node>* label = 0;
       
  2157       for (typename NodeMaps::iterator it = _red_maps.begin();
       
  2158            it != _red_maps.end(); ++it) {
       
  2159         if (it->first == "label") {
       
  2160           label = it->second;
       
  2161           break;
       
  2162         }
       
  2163       }
       
  2164 
       
  2165       if (label == 0) {
       
  2166         for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2167           std::ostringstream os;
       
  2168           os << _graph.id(n);
       
  2169           _node_index.insert(std::make_pair(n, os.str()));
       
  2170         }
       
  2171       } else {
       
  2172         for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2173           std::string value = label->get(n);
       
  2174           _node_index.insert(std::make_pair(n, value));
       
  2175         }
       
  2176       }
       
  2177     }
       
  2178 
       
  2179     void createBlueNodeIndex() {
       
  2180       _writer_bits::MapStorageBase<Node>* label = 0;
       
  2181       for (typename NodeMaps::iterator it = _blue_maps.begin();
       
  2182            it != _blue_maps.end(); ++it) {
       
  2183         if (it->first == "label") {
       
  2184           label = it->second;
       
  2185           break;
       
  2186         }
       
  2187       }
       
  2188 
       
  2189       if (label == 0) {
       
  2190         for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2191           std::ostringstream os;
       
  2192           os << _graph.id(n);
       
  2193           _node_index.insert(std::make_pair(n, os.str()));
       
  2194         }
       
  2195       } else {
       
  2196         for (NodeIt n(_graph); n != INVALID; ++n) {
       
  2197           std::string value = label->get(n);
       
  2198           _node_index.insert(std::make_pair(n, value));
       
  2199         }
       
  2200       }
       
  2201     }
       
  2202 
       
  2203     void writeEdges() {
       
  2204       _writer_bits::MapStorageBase<Edge>* label = 0;
       
  2205       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  2206            it != _edge_maps.end(); ++it) {
       
  2207         if (it->first == "label") {
       
  2208           label = it->second;
       
  2209           break;
       
  2210         }
       
  2211       }
       
  2212 
       
  2213       *_os << "@edges";
       
  2214       if (!_edges_caption.empty()) {
       
  2215         _writer_bits::writeToken(*_os << ' ', _edges_caption);
       
  2216       }
       
  2217       *_os << std::endl;
       
  2218 
       
  2219       *_os << '\t' << '\t';
       
  2220       if (label == 0) {
       
  2221         *_os << "label" << '\t';
       
  2222       }
       
  2223       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  2224            it != _edge_maps.end(); ++it) {
       
  2225         _writer_bits::writeToken(*_os, it->first) << '\t';
       
  2226       }
       
  2227       *_os << std::endl;
       
  2228 
       
  2229       std::vector<Edge> edges;
       
  2230       for (EdgeIt n(_graph); n != INVALID; ++n) {
       
  2231         edges.push_back(n);
       
  2232       }
       
  2233 
       
  2234       if (label == 0) {
       
  2235         IdMap<BGR, Edge> id_map(_graph);
       
  2236         _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
       
  2237         std::sort(edges.begin(), edges.end(), id_less);
       
  2238       } else {
       
  2239         label->sort(edges);
       
  2240       }
       
  2241 
       
  2242       for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
       
  2243         Edge e = edges[i];
       
  2244         _writer_bits::writeToken(*_os, _node_index.
       
  2245                                  find(_graph.redNode(e))->second);
       
  2246         *_os << '\t';
       
  2247         _writer_bits::writeToken(*_os, _node_index.
       
  2248                                  find(_graph.blueNode(e))->second);
       
  2249         *_os << '\t';
       
  2250         if (label == 0) {
       
  2251           std::ostringstream os;
       
  2252           os << _graph.id(e);
       
  2253           _writer_bits::writeToken(*_os, os.str());
       
  2254           *_os << '\t';
       
  2255           _edge_index.insert(std::make_pair(e, os.str()));
       
  2256         }
       
  2257         for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  2258              it != _edge_maps.end(); ++it) {
       
  2259           std::string value = it->second->get(e);
       
  2260           _writer_bits::writeToken(*_os, value);
       
  2261           if (it->first == "label") {
       
  2262             _edge_index.insert(std::make_pair(e, value));
       
  2263           }
       
  2264           *_os << '\t';
       
  2265         }
       
  2266         *_os << std::endl;
       
  2267       }
       
  2268     }
       
  2269 
       
  2270     void createEdgeIndex() {
       
  2271       _writer_bits::MapStorageBase<Edge>* label = 0;
       
  2272       for (typename EdgeMaps::iterator it = _edge_maps.begin();
       
  2273            it != _edge_maps.end(); ++it) {
       
  2274         if (it->first == "label") {
       
  2275           label = it->second;
       
  2276           break;
       
  2277         }
       
  2278       }
       
  2279 
       
  2280       if (label == 0) {
       
  2281         for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  2282           std::ostringstream os;
       
  2283           os << _graph.id(e);
       
  2284           _edge_index.insert(std::make_pair(e, os.str()));
       
  2285         }
       
  2286       } else {
       
  2287         for (EdgeIt e(_graph); e != INVALID; ++e) {
       
  2288           std::string value = label->get(e);
       
  2289           _edge_index.insert(std::make_pair(e, value));
       
  2290         }
       
  2291       }
       
  2292     }
       
  2293 
       
  2294     void writeAttributes() {
       
  2295       if (_attributes.empty()) return;
       
  2296       *_os << "@attributes";
       
  2297       if (!_attributes_caption.empty()) {
       
  2298         _writer_bits::writeToken(*_os << ' ', _attributes_caption);
       
  2299       }
       
  2300       *_os << std::endl;
       
  2301       for (typename Attributes::iterator it = _attributes.begin();
       
  2302            it != _attributes.end(); ++it) {
       
  2303         _writer_bits::writeToken(*_os, it->first) << ' ';
       
  2304         _writer_bits::writeToken(*_os, it->second->get());
       
  2305         *_os << std::endl;
       
  2306       }
       
  2307     }
       
  2308 
       
  2309   public:
       
  2310 
       
  2311     /// \name Execution of the Writer
       
  2312     /// @{
       
  2313 
       
  2314     /// \brief Start the batch processing
       
  2315     ///
       
  2316     /// This function starts the batch processing.
       
  2317     void run() {
       
  2318       if (!_skip_nodes) {
       
  2319         writeRedNodes();
       
  2320         writeBlueNodes();
       
  2321       } else {
       
  2322         createRedNodeIndex();
       
  2323         createBlueNodeIndex();
       
  2324       }
       
  2325       if (!_skip_edges) {
       
  2326         writeEdges();
       
  2327       } else {
       
  2328         createEdgeIndex();
       
  2329       }
       
  2330       writeAttributes();
       
  2331     }
       
  2332 
       
  2333     /// \brief Give back the stream of the writer
       
  2334     ///
       
  2335     /// Give back the stream of the writer
       
  2336     std::ostream& ostream() {
       
  2337       return *_os;
       
  2338     }
       
  2339 
       
  2340     /// @}
       
  2341   };
       
  2342 
       
  2343   /// \ingroup lemon_io
       
  2344   ///
       
  2345   /// \brief Return a \ref BpGraphWriter class
       
  2346   ///
       
  2347   /// This function just returns a \ref BpGraphWriter class.
       
  2348   ///
       
  2349   /// With this function a bipartite graph can be write to a file or output
       
  2350   /// stream in \ref lgf-format "LGF" format with several maps and
       
  2351   /// attributes. For example, with the following code a bipartite
       
  2352   /// weighted matching problem can be written to the standard output,
       
  2353   /// i.e. a graph with a \e weight map on the edges:
       
  2354   ///
       
  2355   ///\code
       
  2356   ///ListBpGraph graph;
       
  2357   ///ListBpGraph::EdgeMap<int> weight(graph);
       
  2358   ///  // Setting the weight map
       
  2359   ///bpGraphWriter(graph, std::cout).
       
  2360   ///  edgeMap("weight", weight).
       
  2361   ///  run();
       
  2362   ///\endcode
       
  2363   ///
       
  2364   /// For a complete documentation, please see the \ref BpGraphWriter
       
  2365   /// class documentation.
       
  2366   /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
       
  2367   /// to the end of the parameter list.
       
  2368   /// \relates BpGraphWriter
       
  2369   /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
       
  2370   /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
       
  2371   template <typename TBGR>
       
  2372   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
       
  2373     BpGraphWriter<TBGR> tmp(graph, os);
       
  2374     return tmp;
       
  2375   }
       
  2376 
       
  2377   /// \brief Return a \ref BpGraphWriter class
       
  2378   ///
       
  2379   /// This function just returns a \ref BpGraphWriter class.
       
  2380   /// \relates BpGraphWriter
       
  2381   /// \sa graphWriter(const TBGR& graph, std::ostream& os)
       
  2382   template <typename TBGR>
       
  2383   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
       
  2384     BpGraphWriter<TBGR> tmp(graph, fn);
       
  2385     return tmp;
       
  2386   }
       
  2387 
       
  2388   /// \brief Return a \ref BpGraphWriter class
       
  2389   ///
       
  2390   /// This function just returns a \ref BpGraphWriter class.
       
  2391   /// \relates BpGraphWriter
       
  2392   /// \sa graphWriter(const TBGR& graph, std::ostream& os)
       
  2393   template <typename TBGR>
       
  2394   BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
       
  2395     BpGraphWriter<TBGR> tmp(graph, fn);
  1608     return tmp;
  2396     return tmp;
  1609   }
  2397   }
  1610 
  2398 
  1611   class SectionWriter;
  2399   class SectionWriter;
  1612 
  2400