736 template <typename Digraph> |
807 template <typename Digraph> |
737 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { |
808 DigraphWriter<Digraph> digraphWriter(const char* fn, Digraph& digraph) { |
738 DigraphWriter<Digraph> tmp(fn, digraph); |
809 DigraphWriter<Digraph> tmp(fn, digraph); |
739 return tmp; |
810 return tmp; |
740 } |
811 } |
|
812 |
|
813 /// \ingroup lemon_io |
|
814 /// |
|
815 /// \brief LGF writer for directed graphs |
|
816 /// |
|
817 /// This utility writes an \ref lgf-format "LGF" file. |
|
818 template <typename _Graph> |
|
819 class GraphWriter { |
|
820 public: |
|
821 |
|
822 typedef _Graph Graph; |
|
823 TEMPLATE_GRAPH_TYPEDEFS(Graph); |
|
824 |
|
825 private: |
|
826 |
|
827 |
|
828 std::ostream* _os; |
|
829 bool local_os; |
|
830 |
|
831 Graph& _graph; |
|
832 |
|
833 std::string _nodes_caption; |
|
834 std::string _edges_caption; |
|
835 std::string _attributes_caption; |
|
836 |
|
837 typedef std::map<Node, std::string> NodeIndex; |
|
838 NodeIndex _node_index; |
|
839 typedef std::map<Edge, std::string> EdgeIndex; |
|
840 EdgeIndex _edge_index; |
|
841 |
|
842 typedef std::vector<std::pair<std::string, |
|
843 _writer_bits::MapStorageBase<Node>* > > NodeMaps; |
|
844 NodeMaps _node_maps; |
|
845 |
|
846 typedef std::vector<std::pair<std::string, |
|
847 _writer_bits::MapStorageBase<Edge>* > >EdgeMaps; |
|
848 EdgeMaps _edge_maps; |
|
849 |
|
850 typedef std::vector<std::pair<std::string, |
|
851 _writer_bits::ValueStorageBase*> > Attributes; |
|
852 Attributes _attributes; |
|
853 |
|
854 bool _skip_nodes; |
|
855 bool _skip_edges; |
|
856 |
|
857 public: |
|
858 |
|
859 /// \brief Constructor |
|
860 /// |
|
861 /// Construct a directed graph writer, which writes to the given |
|
862 /// output stream. |
|
863 GraphWriter(std::ostream& is, Graph& graph) |
|
864 : _os(&is), local_os(false), _graph(graph), |
|
865 _skip_nodes(false), _skip_edges(false) {} |
|
866 |
|
867 /// \brief Constructor |
|
868 /// |
|
869 /// Construct a directed graph writer, which writes to the given |
|
870 /// output file. |
|
871 GraphWriter(const std::string& fn, Graph& graph) |
|
872 : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph), |
|
873 _skip_nodes(false), _skip_edges(false) {} |
|
874 |
|
875 /// \brief Constructor |
|
876 /// |
|
877 /// Construct a directed graph writer, which writes to the given |
|
878 /// output file. |
|
879 GraphWriter(const char* fn, Graph& graph) |
|
880 : _os(new std::ofstream(fn)), local_os(true), _graph(graph), |
|
881 _skip_nodes(false), _skip_edges(false) {} |
|
882 |
|
883 /// \brief Copy constructor |
|
884 /// |
|
885 /// The copy constructor transfers all data from the other writer, |
|
886 /// therefore the copied writer will not be usable more. |
|
887 GraphWriter(GraphWriter& other) |
|
888 : _os(other._os), local_os(other.local_os), _graph(other._graph), |
|
889 _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) { |
|
890 |
|
891 other._os = 0; |
|
892 other.local_os = false; |
|
893 |
|
894 _node_index.swap(other._node_index); |
|
895 _edge_index.swap(other._edge_index); |
|
896 |
|
897 _node_maps.swap(other._node_maps); |
|
898 _edge_maps.swap(other._edge_maps); |
|
899 _attributes.swap(other._attributes); |
|
900 |
|
901 _nodes_caption = other._nodes_caption; |
|
902 _edges_caption = other._edges_caption; |
|
903 _attributes_caption = other._attributes_caption; |
|
904 } |
|
905 |
|
906 /// \brief Destructor |
|
907 ~GraphWriter() { |
|
908 for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
909 it != _node_maps.end(); ++it) { |
|
910 delete it->second; |
|
911 } |
|
912 |
|
913 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
914 it != _edge_maps.end(); ++it) { |
|
915 delete it->second; |
|
916 } |
|
917 |
|
918 for (typename Attributes::iterator it = _attributes.begin(); |
|
919 it != _attributes.end(); ++it) { |
|
920 delete it->second; |
|
921 } |
|
922 |
|
923 if (local_os) { |
|
924 delete _os; |
|
925 } |
|
926 } |
|
927 |
|
928 private: |
|
929 |
|
930 GraphWriter& operator=(const GraphWriter&); |
|
931 |
|
932 public: |
|
933 |
|
934 /// \name Writing rules |
|
935 /// @{ |
|
936 |
|
937 /// \brief Node map reading rule |
|
938 /// |
|
939 /// Add a node map reading rule to the writer. |
|
940 template <typename Map> |
|
941 GraphWriter& nodeMap(const std::string& caption, const Map& map) { |
|
942 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
|
943 _writer_bits::MapStorageBase<Node>* storage = |
|
944 new _writer_bits::MapStorage<Node, Map>(map); |
|
945 _node_maps.push_back(std::make_pair(caption, storage)); |
|
946 return *this; |
|
947 } |
|
948 |
|
949 /// \brief Node map writing rule |
|
950 /// |
|
951 /// Add a node map writing rule with specialized converter to the |
|
952 /// writer. |
|
953 template <typename Map, typename Converter> |
|
954 GraphWriter& nodeMap(const std::string& caption, const Map& map, |
|
955 const Converter& converter = Converter()) { |
|
956 checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>(); |
|
957 _writer_bits::MapStorageBase<Node>* storage = |
|
958 new _writer_bits::MapStorage<Node, Map, Converter>(map, converter); |
|
959 _node_maps.push_back(std::make_pair(caption, storage)); |
|
960 return *this; |
|
961 } |
|
962 |
|
963 /// \brief Edge map writing rule |
|
964 /// |
|
965 /// Add an edge map writing rule to the writer. |
|
966 template <typename Map> |
|
967 GraphWriter& edgeMap(const std::string& caption, const Map& map) { |
|
968 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
|
969 _writer_bits::MapStorageBase<Edge>* storage = |
|
970 new _writer_bits::MapStorage<Edge, Map>(map); |
|
971 _edge_maps.push_back(std::make_pair(caption, storage)); |
|
972 return *this; |
|
973 } |
|
974 |
|
975 /// \brief Edge map writing rule |
|
976 /// |
|
977 /// Add an edge map writing rule with specialized converter to the |
|
978 /// writer. |
|
979 template <typename Map, typename Converter> |
|
980 GraphWriter& edgeMap(const std::string& caption, const Map& map, |
|
981 const Converter& converter = Converter()) { |
|
982 checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>(); |
|
983 _writer_bits::MapStorageBase<Edge>* storage = |
|
984 new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter); |
|
985 _edge_maps.push_back(std::make_pair(caption, storage)); |
|
986 return *this; |
|
987 } |
|
988 |
|
989 /// \brief Arc map writing rule |
|
990 /// |
|
991 /// Add an arc map writing rule to the writer. |
|
992 template <typename Map> |
|
993 GraphWriter& arcMap(const std::string& caption, const Map& map) { |
|
994 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
|
995 _writer_bits::MapStorageBase<Edge>* forward_storage = |
|
996 new _writer_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map); |
|
997 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
|
998 _writer_bits::MapStorageBase<Edge>* backward_storage = |
|
999 new _writer_bits::GraphArcMapStorage<Graph, false, Map>(_graph, map); |
|
1000 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
|
1001 return *this; |
|
1002 } |
|
1003 |
|
1004 /// \brief Arc map writing rule |
|
1005 /// |
|
1006 /// Add an arc map writing rule with specialized converter to the |
|
1007 /// writer. |
|
1008 template <typename Map, typename Converter> |
|
1009 GraphWriter& arcMap(const std::string& caption, const Map& map, |
|
1010 const Converter& converter = Converter()) { |
|
1011 checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>(); |
|
1012 _writer_bits::MapStorageBase<Edge>* forward_storage = |
|
1013 new _writer_bits::GraphArcMapStorage<Graph, true, Map, Converter> |
|
1014 (_graph, map, converter); |
|
1015 _edge_maps.push_back(std::make_pair('+' + caption, forward_storage)); |
|
1016 _writer_bits::MapStorageBase<Edge>* backward_storage = |
|
1017 new _writer_bits::GraphArcMapStorage<Graph, false, Map, Converter> |
|
1018 (_graph, map, converter); |
|
1019 _edge_maps.push_back(std::make_pair('-' + caption, backward_storage)); |
|
1020 return *this; |
|
1021 } |
|
1022 |
|
1023 /// \brief Attribute writing rule |
|
1024 /// |
|
1025 /// Add an attribute writing rule to the writer. |
|
1026 template <typename Value> |
|
1027 GraphWriter& attribute(const std::string& caption, const Value& value) { |
|
1028 _writer_bits::ValueStorageBase* storage = |
|
1029 new _writer_bits::ValueStorage<Value>(value); |
|
1030 _attributes.push_back(std::make_pair(caption, storage)); |
|
1031 return *this; |
|
1032 } |
|
1033 |
|
1034 /// \brief Attribute writing rule |
|
1035 /// |
|
1036 /// Add an attribute writing rule with specialized converter to the |
|
1037 /// writer. |
|
1038 template <typename Value, typename Converter> |
|
1039 GraphWriter& attribute(const std::string& caption, const Value& value, |
|
1040 const Converter& converter = Converter()) { |
|
1041 _writer_bits::ValueStorageBase* storage = |
|
1042 new _writer_bits::ValueStorage<Value, Converter>(value, converter); |
|
1043 _attributes.push_back(std::make_pair(caption, storage)); |
|
1044 return *this; |
|
1045 } |
|
1046 |
|
1047 /// \brief Node writing rule |
|
1048 /// |
|
1049 /// Add a node writing rule to the writer. |
|
1050 GraphWriter& node(const std::string& caption, const Node& node) { |
|
1051 typedef _writer_bits::MapLookUpConverter<Node> Converter; |
|
1052 Converter converter(_node_index); |
|
1053 _writer_bits::ValueStorageBase* storage = |
|
1054 new _writer_bits::ValueStorage<Node, Converter>(node, converter); |
|
1055 _attributes.push_back(std::make_pair(caption, storage)); |
|
1056 return *this; |
|
1057 } |
|
1058 |
|
1059 /// \brief Edge writing rule |
|
1060 /// |
|
1061 /// Add an edge writing rule to writer. |
|
1062 GraphWriter& edge(const std::string& caption, const Edge& edge) { |
|
1063 typedef _writer_bits::MapLookUpConverter<Edge> Converter; |
|
1064 Converter converter(_edge_index); |
|
1065 _writer_bits::ValueStorageBase* storage = |
|
1066 new _writer_bits::ValueStorage<Edge, Converter>(edge, converter); |
|
1067 _attributes.push_back(std::make_pair(caption, storage)); |
|
1068 return *this; |
|
1069 } |
|
1070 |
|
1071 /// \brief Arc writing rule |
|
1072 /// |
|
1073 /// Add an arc writing rule to writer. |
|
1074 GraphWriter& arc(const std::string& caption, const Arc& arc) { |
|
1075 typedef _writer_bits::GraphArcLookUpConverter<Graph> Converter; |
|
1076 Converter converter(_graph, _edge_index); |
|
1077 _writer_bits::ValueStorageBase* storage = |
|
1078 new _writer_bits::ValueStorage<Arc, Converter>(arc, converter); |
|
1079 _attributes.push_back(std::make_pair(caption, storage)); |
|
1080 return *this; |
|
1081 } |
|
1082 |
|
1083 /// \name Select section by name |
|
1084 /// @{ |
|
1085 |
|
1086 /// \brief Set \c \@nodes section to be read |
|
1087 /// |
|
1088 /// Set \c \@nodes section to be read |
|
1089 GraphWriter& nodes(const std::string& caption) { |
|
1090 _nodes_caption = caption; |
|
1091 return *this; |
|
1092 } |
|
1093 |
|
1094 /// \brief Set \c \@edges section to be read |
|
1095 /// |
|
1096 /// Set \c \@edges section to be read |
|
1097 GraphWriter& edges(const std::string& caption) { |
|
1098 _edges_caption = caption; |
|
1099 return *this; |
|
1100 } |
|
1101 |
|
1102 /// \brief Set \c \@attributes section to be read |
|
1103 /// |
|
1104 /// Set \c \@attributes section to be read |
|
1105 GraphWriter& attributes(const std::string& caption) { |
|
1106 _attributes_caption = caption; |
|
1107 return *this; |
|
1108 } |
|
1109 |
|
1110 /// \name Skipping section |
|
1111 /// @{ |
|
1112 |
|
1113 /// \brief Skip writing the node set |
|
1114 /// |
|
1115 /// The \c \@nodes section will be not written to the stream. |
|
1116 GraphWriter& skipNodes() { |
|
1117 LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member"); |
|
1118 return *this; |
|
1119 } |
|
1120 |
|
1121 /// \brief Skip writing edge set |
|
1122 /// |
|
1123 /// The \c \@edges section will be not written to the stream. |
|
1124 GraphWriter& skipEdges() { |
|
1125 LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member"); |
|
1126 return *this; |
|
1127 } |
|
1128 |
|
1129 /// @} |
|
1130 |
|
1131 private: |
|
1132 |
|
1133 void writeNodes() { |
|
1134 _writer_bits::MapStorageBase<Node>* label = 0; |
|
1135 for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
1136 it != _node_maps.end(); ++it) { |
|
1137 if (it->first == "label") { |
|
1138 label = it->second; |
|
1139 break; |
|
1140 } |
|
1141 } |
|
1142 |
|
1143 *_os << "@nodes"; |
|
1144 if (!_nodes_caption.empty()) { |
|
1145 _writer_bits::writeToken(*_os << ' ', _nodes_caption); |
|
1146 } |
|
1147 *_os << std::endl; |
|
1148 |
|
1149 if (label == 0) { |
|
1150 *_os << "label" << '\t'; |
|
1151 } |
|
1152 for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
1153 it != _node_maps.end(); ++it) { |
|
1154 _writer_bits::writeToken(*_os, it->first) << '\t'; |
|
1155 } |
|
1156 *_os << std::endl; |
|
1157 |
|
1158 std::vector<Node> nodes; |
|
1159 for (NodeIt n(_graph); n != INVALID; ++n) { |
|
1160 nodes.push_back(n); |
|
1161 } |
|
1162 |
|
1163 if (label == 0) { |
|
1164 IdMap<Graph, Node> id_map(_graph); |
|
1165 _writer_bits::MapLess<IdMap<Graph, Node> > id_less(id_map); |
|
1166 std::sort(nodes.begin(), nodes.end(), id_less); |
|
1167 } else { |
|
1168 label->sort(nodes); |
|
1169 } |
|
1170 |
|
1171 for (int i = 0; i < static_cast<int>(nodes.size()); ++i) { |
|
1172 Node n = nodes[i]; |
|
1173 if (label == 0) { |
|
1174 std::ostringstream os; |
|
1175 os << _graph.id(n); |
|
1176 _writer_bits::writeToken(*_os, os.str()); |
|
1177 *_os << '\t'; |
|
1178 _node_index.insert(std::make_pair(n, os.str())); |
|
1179 } |
|
1180 for (typename NodeMaps::iterator it = _node_maps.begin(); |
|
1181 it != _node_maps.end(); ++it) { |
|
1182 std::string value = it->second->get(n); |
|
1183 _writer_bits::writeToken(*_os, value); |
|
1184 if (it->first == "label") { |
|
1185 _node_index.insert(std::make_pair(n, value)); |
|
1186 } |
|
1187 *_os << '\t'; |
|
1188 } |
|
1189 *_os << std::endl; |
|
1190 } |
|
1191 } |
|
1192 |
|
1193 void writeEdges() { |
|
1194 _writer_bits::MapStorageBase<Edge>* label = 0; |
|
1195 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
1196 it != _edge_maps.end(); ++it) { |
|
1197 if (it->first == "label") { |
|
1198 label = it->second; |
|
1199 break; |
|
1200 } |
|
1201 } |
|
1202 |
|
1203 *_os << "@edges"; |
|
1204 if (!_edges_caption.empty()) { |
|
1205 _writer_bits::writeToken(*_os << ' ', _edges_caption); |
|
1206 } |
|
1207 *_os << std::endl; |
|
1208 |
|
1209 *_os << '\t' << '\t'; |
|
1210 if (label == 0) { |
|
1211 *_os << "label" << '\t'; |
|
1212 } |
|
1213 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
1214 it != _edge_maps.end(); ++it) { |
|
1215 _writer_bits::writeToken(*_os, it->first) << '\t'; |
|
1216 } |
|
1217 *_os << std::endl; |
|
1218 |
|
1219 std::vector<Edge> edges; |
|
1220 for (EdgeIt n(_graph); n != INVALID; ++n) { |
|
1221 edges.push_back(n); |
|
1222 } |
|
1223 |
|
1224 if (label == 0) { |
|
1225 IdMap<Graph, Edge> id_map(_graph); |
|
1226 _writer_bits::MapLess<IdMap<Graph, Edge> > id_less(id_map); |
|
1227 std::sort(edges.begin(), edges.end(), id_less); |
|
1228 } else { |
|
1229 label->sort(edges); |
|
1230 } |
|
1231 |
|
1232 for (int i = 0; i < static_cast<int>(edges.size()); ++i) { |
|
1233 Edge e = edges[i]; |
|
1234 _writer_bits::writeToken(*_os, _node_index. |
|
1235 find(_graph.u(e))->second); |
|
1236 *_os << '\t'; |
|
1237 _writer_bits::writeToken(*_os, _node_index. |
|
1238 find(_graph.v(e))->second); |
|
1239 *_os << '\t'; |
|
1240 if (label == 0) { |
|
1241 std::ostringstream os; |
|
1242 os << _graph.id(e); |
|
1243 _writer_bits::writeToken(*_os, os.str()); |
|
1244 *_os << '\t'; |
|
1245 _edge_index.insert(std::make_pair(e, os.str())); |
|
1246 } |
|
1247 for (typename EdgeMaps::iterator it = _edge_maps.begin(); |
|
1248 it != _edge_maps.end(); ++it) { |
|
1249 std::string value = it->second->get(e); |
|
1250 _writer_bits::writeToken(*_os, value); |
|
1251 if (it->first == "label") { |
|
1252 _edge_index.insert(std::make_pair(e, value)); |
|
1253 } |
|
1254 *_os << '\t'; |
|
1255 } |
|
1256 *_os << std::endl; |
|
1257 } |
|
1258 } |
|
1259 |
|
1260 void writeAttributes() { |
|
1261 if (_attributes.empty()) return; |
|
1262 *_os << "@attributes"; |
|
1263 if (!_attributes_caption.empty()) { |
|
1264 _writer_bits::writeToken(*_os << ' ', _attributes_caption); |
|
1265 } |
|
1266 *_os << std::endl; |
|
1267 for (typename Attributes::iterator it = _attributes.begin(); |
|
1268 it != _attributes.end(); ++it) { |
|
1269 _writer_bits::writeToken(*_os, it->first) << ' '; |
|
1270 _writer_bits::writeToken(*_os, it->second->get()); |
|
1271 *_os << std::endl; |
|
1272 } |
|
1273 } |
|
1274 |
|
1275 public: |
|
1276 |
|
1277 /// \name Execution of the writer |
|
1278 /// @{ |
|
1279 |
|
1280 /// \brief Start the batch processing |
|
1281 /// |
|
1282 /// This function starts the batch processing |
|
1283 void run() { |
|
1284 if (!_skip_nodes) { |
|
1285 writeNodes(); |
|
1286 } |
|
1287 if (!_skip_edges) { |
|
1288 writeEdges(); |
|
1289 } |
|
1290 writeAttributes(); |
|
1291 } |
|
1292 |
|
1293 /// \brief Gives back the stream of the writer |
|
1294 /// |
|
1295 /// Gives back the stream of the writer |
|
1296 std::ostream& ostream() { |
|
1297 return *_os; |
|
1298 } |
|
1299 |
|
1300 /// @} |
|
1301 }; |
|
1302 |
|
1303 /// \relates GraphWriter |
|
1304 template <typename Graph> |
|
1305 GraphWriter<Graph> graphWriter(std::ostream& os, Graph& graph) { |
|
1306 GraphWriter<Graph> tmp(os, graph); |
|
1307 return tmp; |
|
1308 } |
|
1309 |
|
1310 /// \relates GraphWriter |
|
1311 template <typename Graph> |
|
1312 GraphWriter<Graph> graphWriter(const std::string& fn, Graph& graph) { |
|
1313 GraphWriter<Graph> tmp(fn, graph); |
|
1314 return tmp; |
|
1315 } |
|
1316 |
|
1317 /// \relates GraphWriter |
|
1318 template <typename Graph> |
|
1319 GraphWriter<Graph> graphWriter(const char* fn, Graph& graph) { |
|
1320 GraphWriter<Graph> tmp(fn, graph); |
|
1321 return tmp; |
|
1322 } |
741 } |
1323 } |
742 |
1324 |
743 #endif |
1325 #endif |