1.1 --- a/lemon/lemon_writer.h Sat Oct 20 14:29:12 2007 +0000
1.2 +++ b/lemon/lemon_writer.h Wed Oct 24 16:31:49 2007 +0000
1.3 @@ -144,8 +144,8 @@
1.4 }
1.5
1.6 private:
1.7 + const Graph& graph;
1.8 typename Ref<Map>::Type map;
1.9 - const Graph& graph;
1.10 };
1.11
1.12 template <typename Graph, typename Map>
1.13 @@ -168,8 +168,8 @@
1.14 }
1.15
1.16 private:
1.17 + const Graph& graph;
1.18 typename Ref<Map>::Type map;
1.19 - const Graph& graph;
1.20 };
1.21
1.22 template <typename Graph, typename Map>
1.23 @@ -502,7 +502,7 @@
1.24 /// \c writeLabel() member will be called with a node it will write it's
1.25 /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
1.26 /// then the label map will be the id in the graph. In addition if the
1.27 - /// the \c _forceSort is true then the writer will write the edges
1.28 + /// the \c _forceSort is true then the writer will write the nodes
1.29 /// sorted by the labels.
1.30 ///
1.31 /// \relates LemonWriter
1.32 @@ -680,6 +680,300 @@
1.33 };
1.34
1.35 /// \ingroup section_io
1.36 + /// \brief SectionWriter for writing a bipartite graph's nodeset.
1.37 + ///
1.38 + /// The lemon format can store multiple bipartite graph nodesets
1.39 + /// with several maps. The nodeset section's header line is \c
1.40 + /// \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name may be empty.
1.41 + ///
1.42 + /// The first line of the section contains the names of the maps separated
1.43 + /// with white spaces. Each next lines describes a node in the nodeset, and
1.44 + /// contains the mapped values for each map.
1.45 + ///
1.46 + /// If the nodeset contains an \c "label" named map then it will be regarded
1.47 + /// as label map. This map should contain only unique values and when the
1.48 + /// \c writeLabel() member will be called with a node it will write it's
1.49 + /// label. Otherwise if the \c _forceLabelMap constructor parameter is true
1.50 + /// then the label map will be the id in the graph. In addition if the
1.51 + /// the \c _forceSort is true then the writer will write the edges
1.52 + /// sorted by the labels.
1.53 + ///
1.54 + /// \relates LemonWriter
1.55 + template <typename _Graph, typename _Traits = DefaultWriterTraits>
1.56 + class BpNodeSetWriter : public LemonWriter::SectionWriter {
1.57 + typedef LemonWriter::SectionWriter Parent;
1.58 + public:
1.59 +
1.60 + typedef _Graph Graph;
1.61 + typedef _Traits Traits;
1.62 + typedef typename Graph::Node Node;
1.63 +
1.64 + /// \brief Constructor.
1.65 + ///
1.66 + /// Constructor for BpNodeSetWriter. It creates the BpNodeSetWriter and
1.67 + /// attach it into the given LemonWriter. If the \c _forceLabelMap
1.68 + /// parameter is true then the writer will write own label map when
1.69 + /// the user does not give "label" named map. In addition if the
1.70 + /// the \c _forceSort is true then the writer will write the nodes
1.71 + /// sorted by the labels.
1.72 + BpNodeSetWriter(LemonWriter& _writer, const Graph& _graph,
1.73 + const std::string& _name = std::string(),
1.74 + bool _forceLabelMap = true, bool _forceSort = true)
1.75 + : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap),
1.76 + forceSort(_forceSort), graph(_graph), name(_name) {}
1.77 +
1.78 + /// \brief Destructor.
1.79 + ///
1.80 + /// Destructor for BpNodeSetWriter.
1.81 + virtual ~BpNodeSetWriter() {
1.82 + typename MapWriters::iterator it;
1.83 + for (it = writers.begin(); it != writers.end(); ++it) {
1.84 + delete it->second;
1.85 + }
1.86 + }
1.87 +
1.88 + private:
1.89 + BpNodeSetWriter(const BpNodeSetWriter&);
1.90 + void operator=(const BpNodeSetWriter&);
1.91 +
1.92 + public:
1.93 +
1.94 + /// \brief Add a new A-node map writer command for the writer.
1.95 + ///
1.96 + /// Add a new A-node map writer command for the writer.
1.97 + template <typename Map>
1.98 + BpNodeSetWriter& writeANodeMap(std::string label, const Map& map) {
1.99 + return writeANodeMap<typename Traits::
1.100 + template Writer<typename Map::Value>, Map>(label, map);
1.101 + }
1.102 +
1.103 + /// \brief Add a new A-node map writer command for the writer.
1.104 + ///
1.105 + /// Add a new A-node map writer command for the writer.
1.106 + template <typename ItemWriter, typename Map>
1.107 + BpNodeSetWriter& writeANodeMap(std::string label, const Map& map,
1.108 + const ItemWriter& iw = ItemWriter()) {
1.109 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.110 + checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1.111 + if (label == "label") {
1.112 + throw IoParameterError("Label cannot be A-node map");
1.113 + }
1.114 + awriters.push_back(make_pair(label, new _writer_bits::
1.115 + MapWriter<Node, Map, ItemWriter>(map, iw)));
1.116 + return *this;
1.117 + }
1.118 +
1.119 + /// \brief Add a new B-node map writer command for the writer.
1.120 + ///
1.121 + /// Add a new B-node map writer command for the writer.
1.122 + template <typename Map>
1.123 + BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map) {
1.124 + return writeBNodeMap<typename Traits::
1.125 + template Writer<typename Map::Value>, Map>(label, map);
1.126 + }
1.127 +
1.128 + /// \brief Add a new B-node map writer command for the writer.
1.129 + ///
1.130 + /// Add a new B-node map writer command for the writer.
1.131 + template <typename ItemWriter, typename Map>
1.132 + BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map,
1.133 + const ItemWriter& iw = ItemWriter()) {
1.134 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.135 + checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1.136 + if (label == "label") {
1.137 + throw IoParameterError("Label cannot be B-node map");
1.138 + }
1.139 + bwriters.push_back(make_pair(label, new _writer_bits::
1.140 + MapWriter<Node, Map, ItemWriter>(map, iw)));
1.141 + return *this;
1.142 + }
1.143 +
1.144 + /// \brief Add a new node map writer command for the writer.
1.145 + ///
1.146 + /// Add a new node map writer command for the writer.
1.147 + template <typename Map>
1.148 + BpNodeSetWriter& writeNodeMap(std::string label, const Map& map) {
1.149 + return writeNodeMap<typename Traits::
1.150 + template Writer<typename Map::Value>, Map>(label, map);
1.151 + }
1.152 +
1.153 + /// \brief Add a new node map writer command for the writer.
1.154 + ///
1.155 + /// Add a new node map writer command for the writer.
1.156 + template <typename ItemWriter, typename Map>
1.157 + BpNodeSetWriter& writeNodeMap(std::string label, const Map& map,
1.158 + const ItemWriter& iw = ItemWriter()) {
1.159 + checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
1.160 + checkConcept<_writer_bits::ItemWriter<typename Map::Value>,ItemWriter>();
1.161 + writers.push_back(make_pair(label, new _writer_bits::
1.162 + MapWriter<Node, Map, ItemWriter>(map, iw)));
1.163 + return *this;
1.164 + }
1.165 +
1.166 + protected:
1.167 +
1.168 + /// \brief The header of the section.
1.169 + ///
1.170 + /// It gives back the header of the section.
1.171 + virtual std::string header() {
1.172 + return "@bpnodeset " + name;
1.173 + }
1.174 +
1.175 + /// \brief Writer function of the section.
1.176 + ///
1.177 + /// Write the content of the section.
1.178 + virtual void write(std::ostream& os) {
1.179 + for (int i = 0; i < int(writers.size()); ++i) {
1.180 + if (writers[i].first == "label") {
1.181 + labelMap = writers[i].second;
1.182 + forceLabelMap = false;
1.183 + break;
1.184 + }
1.185 + }
1.186 + {
1.187 + os << "&anodeset ";
1.188 + std::vector<Node> items;
1.189 + for (typename Graph::ANodeIt it(graph); it != INVALID; ++it) {
1.190 + items.push_back(it);
1.191 + }
1.192 + if (forceSort) {
1.193 + if (labelMap) {
1.194 + labelMap->sort(items);
1.195 + } else {
1.196 + typedef IdMap<Graph, Node> Map;
1.197 + Map map(graph);
1.198 + _writer_bits::ComposeLess<Map> less(map);
1.199 + std::sort(items.begin(), items.end(), less);
1.200 + }
1.201 + }
1.202 + if (forceLabelMap) {
1.203 + os << "label\t";
1.204 + }
1.205 + for (int i = 0; i < int(writers.size()); ++i) {
1.206 + os << writers[i].first << '\t';
1.207 + }
1.208 + for (int i = 0; i < int(awriters.size()); ++i) {
1.209 + os << awriters[i].first << '\t';
1.210 + }
1.211 + os << std::endl;
1.212 + for (typename std::vector<Node>::iterator it = items.begin();
1.213 + it != items.end(); ++it) {
1.214 + if (forceLabelMap) {
1.215 + os << graph.id(*it) << '\t';
1.216 + }
1.217 + for (int i = 0; i < int(writers.size()); ++i) {
1.218 + writers[i].second->write(os, *it);
1.219 + os << '\t';
1.220 + }
1.221 + for (int i = 0; i < int(awriters.size()); ++i) {
1.222 + awriters[i].second->write(os, *it);
1.223 + os << '\t';
1.224 + }
1.225 + os << std::endl;
1.226 + }
1.227 + }
1.228 + {
1.229 + os << "&bnodeset ";
1.230 + std::vector<Node> items;
1.231 + for (typename Graph::BNodeIt it(graph); it != INVALID; ++it) {
1.232 + items.push_back(it);
1.233 + }
1.234 + if (forceSort) {
1.235 + if (labelMap) {
1.236 + labelMap->sort(items);
1.237 + } else {
1.238 + typedef IdMap<Graph, Node> Map;
1.239 + Map map(graph);
1.240 + _writer_bits::ComposeLess<Map> less(map);
1.241 + std::sort(items.begin(), items.end(), less);
1.242 + }
1.243 + }
1.244 + if (forceLabelMap) {
1.245 + os << "label\t";
1.246 + }
1.247 + for (int i = 0; i < int(writers.size()); ++i) {
1.248 + os << writers[i].first << '\t';
1.249 + }
1.250 + for (int i = 0; i < int(bwriters.size()); ++i) {
1.251 + os << bwriters[i].first << '\t';
1.252 + }
1.253 + os << std::endl;
1.254 + for (typename std::vector<Node>::iterator it = items.begin();
1.255 + it != items.end(); ++it) {
1.256 + if (forceLabelMap) {
1.257 + os << graph.id(*it) << '\t';
1.258 + }
1.259 + for (int i = 0; i < int(writers.size()); ++i) {
1.260 + writers[i].second->write(os, *it);
1.261 + os << '\t';
1.262 + }
1.263 + for (int i = 0; i < int(bwriters.size()); ++i) {
1.264 + bwriters[i].second->write(os, *it);
1.265 + os << '\t';
1.266 + }
1.267 + os << std::endl;
1.268 + }
1.269 + }
1.270 + }
1.271 +
1.272 + public:
1.273 +
1.274 + /// \brief Returns true if the nodeset can write the labels of the nodes.
1.275 + ///
1.276 + /// Returns true if the nodeset can write the labels of the nodes.
1.277 + /// It is possible only if a "label" named map was written or the
1.278 + /// \c _forceLabelMap constructor parameter was true.
1.279 + bool isLabelWriter() const {
1.280 + return labelMap != 0 || forceLabelMap;
1.281 + }
1.282 +
1.283 + /// \brief Write the label of the given node.
1.284 + ///
1.285 + /// It writes the label of the given node. If there was written a "label"
1.286 + /// named map then it will write the map value belongs to the node.
1.287 + /// Otherwise if the \c forceLabel parameter was true it will write
1.288 + /// its label in the graph.
1.289 + void writeLabel(std::ostream& os, const Node& item) const {
1.290 + if (forceLabelMap) {
1.291 + os << graph.id(item);
1.292 + } else {
1.293 + labelMap->write(os, item);
1.294 + }
1.295 + }
1.296 +
1.297 + /// \brief Sorts the given node vector by label.
1.298 + ///
1.299 + /// Sorts the given node vector by label. If there was written an
1.300 + /// "label" named map then the vector will be sorted by the values
1.301 + /// of this map. Otherwise if the \c forceLabel parameter was true
1.302 + /// it will be sorted by its id in the graph.
1.303 + void sortByLabel(std::vector<Node>& nodes) const {
1.304 + if (labelMap) {
1.305 + labelMap->sort(nodes);
1.306 + } else {
1.307 + typedef IdMap<Graph, Node> Map;
1.308 + Map map(graph);
1.309 + _writer_bits::ComposeLess<Map> less(map);
1.310 + std::sort(nodes.begin(), nodes.end(), less);
1.311 + }
1.312 + }
1.313 +
1.314 + private:
1.315 +
1.316 + typedef std::vector<std::pair<std::string, _writer_bits::
1.317 + MapWriterBase<Node>*> > MapWriters;
1.318 + MapWriters awriters, bwriters, writers;
1.319 +
1.320 + _writer_bits::MapWriterBase<Node>* labelMap;
1.321 + bool forceLabelMap;
1.322 + bool forceSort;
1.323 +
1.324 + const Graph& graph;
1.325 + std::string name;
1.326 +
1.327 + };
1.328 +
1.329 + /// \ingroup section_io
1.330 /// \brief SectionWriter for writing a graph's edgesets.
1.331 ///
1.332 /// The lemon format can store multiple graph edgesets with several maps.