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 |