980 std::string name; |
1011 std::string name; |
981 _reader_bits::SkipReader<Node, DefaultSkipper> skipper; |
1012 _reader_bits::SkipReader<Node, DefaultSkipper> skipper; |
982 |
1013 |
983 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter; |
1014 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter; |
984 }; |
1015 }; |
|
1016 |
|
1017 /// \ingroup section_io |
|
1018 /// \brief SectionReader for reading a bipartite graph's nodeset. |
|
1019 /// |
|
1020 /// The lemon format can store multiple bipartite graph nodesets |
|
1021 /// with several maps. The bipartite graph nodeset section's header |
|
1022 /// line is \c \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name |
|
1023 /// may be empty. |
|
1024 /// |
|
1025 /// The first line of the section contains \c "&anodeset" and the |
|
1026 /// the names of the A-node maps and regular maps separated with |
|
1027 /// white spaces. Each next lines describes an A-node in the anodeset, |
|
1028 /// and contains the mapped values for each map. If one of the line |
|
1029 /// starts with \c "&bnodeset" then this line contains the names of |
|
1030 /// the B-node maps and the regular node maps. And the remaining lines |
|
1031 /// contains the mapped values to the B-nodes. |
|
1032 /// |
|
1033 /// If there is "label" named map then it should be defined in both |
|
1034 /// nodeset, and it will be regarded as id map. This map should |
|
1035 /// contain only unique values and when the \c readLabel() member |
|
1036 /// will read a value from the given stream it will give back that |
|
1037 /// node which is mapped to this value. |
|
1038 /// |
|
1039 /// \relates LemonReader |
|
1040 template <typename _Graph, typename _Traits = DefaultReaderTraits> |
|
1041 class BpNodeSetReader : public LemonReader::SectionReader { |
|
1042 typedef LemonReader::SectionReader Parent; |
|
1043 public: |
|
1044 |
|
1045 typedef _Graph Graph; |
|
1046 typedef _Traits Traits; |
|
1047 typedef typename Graph::Node Node; |
|
1048 typedef typename Traits::Skipper DefaultSkipper; |
|
1049 |
|
1050 /// \brief Constructor. |
|
1051 /// |
|
1052 /// Constructor for BpNodeSetReader. It creates the BpNodeSetReader and |
|
1053 /// attach it into the given LemonReader. The nodeset reader will |
|
1054 /// add the read nodes to the given Graph. The reader will read |
|
1055 /// the section when the \c section_name and the \c _name are the same. |
|
1056 BpNodeSetReader(LemonReader& _reader, |
|
1057 Graph& _graph, |
|
1058 const std::string& _name = std::string(), |
|
1059 const DefaultSkipper& _skipper = DefaultSkipper()) |
|
1060 : Parent(_reader), graph(_graph), name(_name), skipper(_skipper) {} |
|
1061 |
|
1062 |
|
1063 /// \brief Destructor. |
|
1064 /// |
|
1065 /// Destructor for BpNodeSetReader. |
|
1066 virtual ~BpNodeSetReader() { |
|
1067 for (typename MapReaders::iterator it = readers.begin(); |
|
1068 it != readers.end(); ++it) { |
|
1069 delete it->second; |
|
1070 } |
|
1071 } |
|
1072 |
|
1073 private: |
|
1074 BpNodeSetReader(const BpNodeSetReader&); |
|
1075 void operator=(const BpNodeSetReader&); |
|
1076 |
|
1077 public: |
|
1078 |
|
1079 /// \brief Add a new node map reader command for the reader. |
|
1080 /// |
|
1081 /// Add a new node map reader command for the reader. |
|
1082 template <typename Map> |
|
1083 BpNodeSetReader& readNodeMap(std::string label, Map& map) { |
|
1084 return _readMap< |
|
1085 typename Traits::template Reader<typename Map::Value>, Map, |
|
1086 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1087 } |
|
1088 |
|
1089 template <typename Map> |
|
1090 BpNodeSetReader& readNodeMap(std::string label, const Map& map) { |
|
1091 return _readMap< |
|
1092 typename Traits::template Reader<typename Map::Value>, Map, |
|
1093 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1094 } |
|
1095 |
|
1096 /// \brief Add a new node map reader command for the reader. |
|
1097 /// |
|
1098 /// Add a new node map reader command for the reader. |
|
1099 template <typename ItemReader, typename Map> |
|
1100 BpNodeSetReader& readNodeMap(std::string label, Map& map, |
|
1101 const ItemReader& ir = ItemReader()) { |
|
1102 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1103 (label, map, ir); |
|
1104 } |
|
1105 |
|
1106 template <typename ItemReader, typename Map> |
|
1107 BpNodeSetReader& readNodeMap(std::string label, const Map& map, |
|
1108 const ItemReader& ir = ItemReader()) { |
|
1109 return _readMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1110 (label, map, ir); |
|
1111 } |
|
1112 |
|
1113 private: |
|
1114 |
|
1115 template <typename ItemReader, typename Map, typename MapParameter> |
|
1116 BpNodeSetReader& _readMap(std::string label, MapParameter map, |
|
1117 const ItemReader& ir = ItemReader()) { |
|
1118 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
|
1119 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>(); |
|
1120 if (areaders.find(label) != areaders.end() || |
|
1121 breaders.find(label) != breaders.end() || |
|
1122 readers.find(label) != readers.end()) { |
|
1123 ErrorMessage msg; |
|
1124 msg << "Multiple read rule for node map: " << label; |
|
1125 throw IoParameterError(msg.message()); |
|
1126 } |
|
1127 readers.insert(make_pair(label, new _reader_bits:: |
|
1128 MapReader<Node, Map, ItemReader>(map, ir))); |
|
1129 return *this; |
|
1130 } |
|
1131 |
|
1132 public: |
|
1133 |
|
1134 /// \brief Add a new A-node map reader command for the reader. |
|
1135 /// |
|
1136 /// Add a new A-node map reader command for the reader. |
|
1137 template <typename Map> |
|
1138 BpNodeSetReader& readANodeMap(std::string label, Map& map) { |
|
1139 return _readAMap< |
|
1140 typename Traits::template Reader<typename Map::Value>, Map, |
|
1141 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1142 } |
|
1143 |
|
1144 template <typename Map> |
|
1145 BpNodeSetReader& readANodeMap(std::string label, const Map& map) { |
|
1146 return _readAMap< |
|
1147 typename Traits::template Reader<typename Map::Value>, Map, |
|
1148 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1149 } |
|
1150 |
|
1151 /// \brief Add a new A-node map reader command for the reader. |
|
1152 /// |
|
1153 /// Add a new A-node map reader command for the reader. |
|
1154 template <typename ItemReader, typename Map> |
|
1155 BpNodeSetReader& readANodeMap(std::string label, Map& map, |
|
1156 const ItemReader& ir = ItemReader()) { |
|
1157 return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1158 (label, map, ir); |
|
1159 } |
|
1160 |
|
1161 template <typename ItemReader, typename Map> |
|
1162 BpNodeSetReader& readANodeMap(std::string label, const Map& map, |
|
1163 const ItemReader& ir = ItemReader()) { |
|
1164 return _readAMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1165 (label, map, ir); |
|
1166 } |
|
1167 |
|
1168 private: |
|
1169 |
|
1170 template <typename ItemReader, typename Map, typename MapParameter> |
|
1171 BpNodeSetReader& _readAMap(std::string label, MapParameter map, |
|
1172 const ItemReader& ir = ItemReader()) { |
|
1173 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
|
1174 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>(); |
|
1175 if (label == "label") { |
|
1176 throw IoParameterError("Label cannot be A-node map"); |
|
1177 } |
|
1178 if (areaders.find(label) != areaders.end() || |
|
1179 readers.find(label) != readers.end()) { |
|
1180 ErrorMessage msg; |
|
1181 msg << "Multiple read rule for A-node map: " << label; |
|
1182 throw IoParameterError(msg.message()); |
|
1183 } |
|
1184 areaders.insert(make_pair(label, new _reader_bits:: |
|
1185 MapReader<Node, Map, ItemReader>(map, ir))); |
|
1186 return *this; |
|
1187 } |
|
1188 |
|
1189 public: |
|
1190 |
|
1191 /// \brief Add a new B-node map reader command for the reader. |
|
1192 /// |
|
1193 /// Add a new B-node map reader command for the reader. |
|
1194 template <typename Map> |
|
1195 BpNodeSetReader& readBNodeMap(std::string label, Map& map) { |
|
1196 return _readBMap< |
|
1197 typename Traits::template Reader<typename Map::Value>, Map, |
|
1198 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1199 } |
|
1200 |
|
1201 template <typename Map> |
|
1202 BpNodeSetReader& readBNodeMap(std::string label, const Map& map) { |
|
1203 return _readBMap< |
|
1204 typename Traits::template Reader<typename Map::Value>, Map, |
|
1205 typename _reader_bits::Arg<Map>::Type>(label, map); |
|
1206 } |
|
1207 |
|
1208 /// \brief Add a new B-node map reader command for the reader. |
|
1209 /// |
|
1210 /// Add a new B-node map reader command for the reader. |
|
1211 template <typename ItemReader, typename Map> |
|
1212 BpNodeSetReader& readBNodeMap(std::string label, Map& map, |
|
1213 const ItemReader& ir = ItemReader()) { |
|
1214 return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1215 (label, map, ir); |
|
1216 } |
|
1217 |
|
1218 template <typename ItemReader, typename Map> |
|
1219 BpNodeSetReader& readBNodeMap(std::string label, const Map& map, |
|
1220 const ItemReader& ir = ItemReader()) { |
|
1221 return _readBMap<ItemReader, Map, typename _reader_bits::Arg<Map>::Type> |
|
1222 (label, map, ir); |
|
1223 } |
|
1224 |
|
1225 private: |
|
1226 |
|
1227 template <typename ItemReader, typename Map, typename MapParameter> |
|
1228 BpNodeSetReader& _readBMap(std::string label, MapParameter map, |
|
1229 const ItemReader& ir = ItemReader()) { |
|
1230 checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>(); |
|
1231 checkConcept<_reader_bits::ItemReader<typename Map::Value>, ItemReader>(); |
|
1232 if (label == "label") { |
|
1233 throw IoParameterError("Label cannot be B-node map"); |
|
1234 } |
|
1235 if (breaders.find(label) != breaders.end() || |
|
1236 readers.find(label) != readers.end()) { |
|
1237 ErrorMessage msg; |
|
1238 msg << "Multiple read rule for B-node map: " << label; |
|
1239 throw IoParameterError(msg.message()); |
|
1240 } |
|
1241 breaders.insert(make_pair(label, new _reader_bits:: |
|
1242 MapReader<Node, Map, ItemReader>(map, ir))); |
|
1243 return *this; |
|
1244 } |
|
1245 |
|
1246 public: |
|
1247 |
|
1248 /// \brief Add a new node map skipper command for the reader. |
|
1249 /// |
|
1250 /// Add a new node map skipper command for the reader. |
|
1251 template <typename ItemReader> |
|
1252 BpNodeSetReader& skipNodeMap(std::string label, |
|
1253 const ItemReader& ir = ItemReader()) { |
|
1254 if (areaders.find(label) != areaders.end() || |
|
1255 breaders.find(label) != breaders.end() || |
|
1256 readers.find(label) != readers.end()) { |
|
1257 ErrorMessage msg; |
|
1258 msg << "Multiple read rule for node map: " << label; |
|
1259 throw IoParameterError(msg.message()); |
|
1260 } |
|
1261 readers.insert(make_pair(label, new _reader_bits:: |
|
1262 SkipReader<Node, ItemReader>(ir))); |
|
1263 return *this; |
|
1264 } |
|
1265 |
|
1266 /// \brief Add a new A-node map skipper command for the reader. |
|
1267 /// |
|
1268 /// Add a new A-node map skipper command for the reader. |
|
1269 template <typename ItemReader> |
|
1270 BpNodeSetReader& skipANodeMap(std::string label, |
|
1271 const ItemReader& ir = ItemReader()) { |
|
1272 if (label == "label") { |
|
1273 throw IoParameterError("Label cannot be A-node map"); |
|
1274 } |
|
1275 if (areaders.find(label) != areaders.end() || |
|
1276 readers.find(label) != readers.end()) { |
|
1277 ErrorMessage msg; |
|
1278 msg << "Multiple read rule for A-node map: " << label; |
|
1279 throw IoParameterError(msg.message()); |
|
1280 } |
|
1281 areaders.insert(make_pair(label, new _reader_bits:: |
|
1282 SkipReader<Node, ItemReader>(ir))); |
|
1283 return *this; |
|
1284 } |
|
1285 |
|
1286 /// \brief Add a new B-node map skipper command for the reader. |
|
1287 /// |
|
1288 /// Add a new B-node map skipper command for the reader. |
|
1289 template <typename ItemReader> |
|
1290 BpNodeSetReader& skipBNodeMap(std::string label, |
|
1291 const ItemReader& ir = ItemReader()) { |
|
1292 if (label == "label") { |
|
1293 throw IoParameterError("Label cannot be B-node map"); |
|
1294 } |
|
1295 if (breaders.find(label) != breaders.end() || |
|
1296 readers.find(label) != readers.end()) { |
|
1297 ErrorMessage msg; |
|
1298 msg << "Multiple read rule for B-node map: " << label; |
|
1299 throw IoParameterError(msg.message()); |
|
1300 } |
|
1301 breaders.insert(make_pair(label, new _reader_bits:: |
|
1302 SkipReader<Node, ItemReader>(ir))); |
|
1303 return *this; |
|
1304 } |
|
1305 |
|
1306 |
|
1307 protected: |
|
1308 |
|
1309 /// \brief Gives back true when the SectionReader can process |
|
1310 /// the section with the given header line. |
|
1311 /// |
|
1312 /// It gives back true when the header line starts with \c \@nodeset, |
|
1313 /// and the header line's name and the nodeset's name are the same. |
|
1314 virtual bool header(const std::string& line) { |
|
1315 std::istringstream ls(line); |
|
1316 std::string command; |
|
1317 std::string id; |
|
1318 ls >> command >> id; |
|
1319 return command == "@bpnodeset" && name == id; |
|
1320 } |
|
1321 |
|
1322 /// \brief Reader function of the section. |
|
1323 /// |
|
1324 /// It reads the content of the section. |
|
1325 virtual void read(std::istream& is) { |
|
1326 std::string line; |
|
1327 { |
|
1328 std::vector<_reader_bits::MapReaderBase<Node>* > index; |
|
1329 { |
|
1330 getline(is, line); |
|
1331 std::istringstream ls(line); |
|
1332 std::string id; |
|
1333 ls >> id; |
|
1334 if (id != "&anodeset") { |
|
1335 throw IoParameterError("Cannot find &anodeset subsection"); |
|
1336 } |
|
1337 while (ls >> id) { |
|
1338 typename MapReaders::iterator it = readers.find(id); |
|
1339 typename MapReaders::iterator ait = areaders.find(id); |
|
1340 if (it != readers.end()) { |
|
1341 it->second->touch(); |
|
1342 index.push_back(it->second); |
|
1343 } else if (ait != areaders.end()) { |
|
1344 ait->second->touch(); |
|
1345 index.push_back(ait->second); |
|
1346 } |
|
1347 if (id == "label") { |
|
1348 inverter.reset(index.back()->getInverter()); |
|
1349 index.back() = inverter.get(); |
|
1350 } |
|
1351 } |
|
1352 } |
|
1353 for (typename MapReaders::iterator it = areaders.begin(); |
|
1354 it != areaders.end(); ++it) { |
|
1355 if (!it->second->touched()) { |
|
1356 ErrorMessage msg; |
|
1357 msg << "Map not found in file: " << it->first; |
|
1358 throw IoParameterError(msg.message()); |
|
1359 } |
|
1360 } |
|
1361 for (typename MapReaders::iterator it = readers.begin(); |
|
1362 it != readers.end(); ++it) { |
|
1363 if (!it->second->touched()) { |
|
1364 ErrorMessage msg; |
|
1365 msg << "Map not found in file: " << it->first; |
|
1366 throw IoParameterError(msg.message()); |
|
1367 } |
|
1368 it->second->touch(false); |
|
1369 } |
|
1370 |
|
1371 while (getline(is, line)) { |
|
1372 if (line[0] == '&') { |
|
1373 std::istringstream ls(line); |
|
1374 std::string id; |
|
1375 ls >> id; |
|
1376 if (id == "&bnodeset") break; |
|
1377 } |
|
1378 Node node = graph.addANode(); |
|
1379 std::istringstream ls(line); |
|
1380 for (int i = 0; i < int(index.size()); ++i) { |
|
1381 index[i]->read(ls, node); |
|
1382 } |
|
1383 } |
|
1384 } |
|
1385 |
|
1386 { |
|
1387 std::vector<_reader_bits::MapReaderBase<Node>* > index; |
|
1388 { |
|
1389 std::istringstream ls(line); |
|
1390 std::string id; |
|
1391 ls >> id; |
|
1392 if (id != "&bnodeset") { |
|
1393 throw IoParameterError("Cannot find &bnodeset subsection"); |
|
1394 } |
|
1395 while (ls >> id) { |
|
1396 typename MapReaders::iterator it = readers.find(id); |
|
1397 typename MapReaders::iterator bit = breaders.find(id); |
|
1398 if (it != readers.end()) { |
|
1399 it->second->touch(); |
|
1400 index.push_back(it->second); |
|
1401 } else if (bit != breaders.end()) { |
|
1402 bit->second->touch(); |
|
1403 index.push_back(bit->second); |
|
1404 } |
|
1405 if (id == "label" && inverter.get() != 0) { |
|
1406 index.back() = inverter.get(); |
|
1407 } |
|
1408 } |
|
1409 } |
|
1410 for (typename MapReaders::iterator it = breaders.begin(); |
|
1411 it != breaders.end(); ++it) { |
|
1412 if (!it->second->touched()) { |
|
1413 ErrorMessage msg; |
|
1414 msg << "Map not found in file: " << it->first; |
|
1415 throw IoParameterError(msg.message()); |
|
1416 } |
|
1417 } |
|
1418 for (typename MapReaders::iterator it = readers.begin(); |
|
1419 it != readers.end(); ++it) { |
|
1420 if (!it->second->touched()) { |
|
1421 ErrorMessage msg; |
|
1422 msg << "Map not found in file: " << it->first; |
|
1423 throw IoParameterError(msg.message()); |
|
1424 } |
|
1425 } |
|
1426 while (getline(is, line)) { |
|
1427 Node node = graph.addBNode(); |
|
1428 std::istringstream ls(line); |
|
1429 for (int i = 0; i < int(index.size()); ++i) { |
|
1430 index[i]->read(ls, node); |
|
1431 } |
|
1432 } |
|
1433 } |
|
1434 } |
|
1435 |
|
1436 virtual void missing() { |
|
1437 if (readers.empty()) return; |
|
1438 ErrorMessage msg; |
|
1439 msg << "BpNodeSet section not found in file: @bpnodeset " << name; |
|
1440 throw IoParameterError(msg.message()); |
|
1441 } |
|
1442 |
|
1443 public: |
|
1444 |
|
1445 /// \brief Returns true if the nodeset can give back the node by its label. |
|
1446 /// |
|
1447 /// Returns true if the nodeset can give back the node by its label. |
|
1448 /// It is possible only if an "label" named map was read. |
|
1449 bool isLabelReader() const { |
|
1450 return inverter.get() != 0; |
|
1451 } |
|
1452 |
|
1453 /// \brief Gives back the node by its label. |
|
1454 /// |
|
1455 /// It reads an id from the stream and gives back which node belongs to |
|
1456 /// it. It is possible only if there was read an "label" named map. |
|
1457 void readLabel(std::istream& is, Node& node) const { |
|
1458 node = inverter->read(is); |
|
1459 } |
|
1460 |
|
1461 private: |
|
1462 |
|
1463 typedef std::map<std::string, _reader_bits::MapReaderBase<Node>*> |
|
1464 MapReaders; |
|
1465 |
|
1466 MapReaders areaders, breaders, readers; |
|
1467 |
|
1468 Graph& graph; |
|
1469 std::string name; |
|
1470 _reader_bits::SkipReader<Node, DefaultSkipper> skipper; |
|
1471 |
|
1472 std::auto_ptr<_reader_bits::MapInverterBase<Node> > inverter; |
|
1473 }; |
|
1474 |
985 |
1475 |
986 /// \ingroup section_io |
1476 /// \ingroup section_io |
987 /// \brief SectionReader for reading a graph's edgeset. |
1477 /// \brief SectionReader for reading a graph's edgeset. |
988 /// |
1478 /// |
989 /// The lemon format can store multiple graph edgesets with several maps. |
1479 /// The lemon format can store multiple graph edgesets with several maps. |