diff -r 1af977819111 -r 9c23c3762bc5 lemon/lemon_writer.h --- a/lemon/lemon_writer.h Sat Oct 20 14:29:12 2007 +0000 +++ b/lemon/lemon_writer.h Wed Oct 24 16:31:49 2007 +0000 @@ -144,8 +144,8 @@ } private: + const Graph& graph; typename Ref::Type map; - const Graph& graph; }; template @@ -168,8 +168,8 @@ } private: + const Graph& graph; typename Ref::Type map; - const Graph& graph; }; template @@ -502,7 +502,7 @@ /// \c writeLabel() member will be called with a node it will write it's /// label. Otherwise if the \c _forceLabelMap constructor parameter is true /// then the label map will be the id in the graph. In addition if the - /// the \c _forceSort is true then the writer will write the edges + /// the \c _forceSort is true then the writer will write the nodes /// sorted by the labels. /// /// \relates LemonWriter @@ -680,6 +680,300 @@ }; /// \ingroup section_io + /// \brief SectionWriter for writing a bipartite graph's nodeset. + /// + /// The lemon format can store multiple bipartite graph nodesets + /// with several maps. The nodeset section's header line is \c + /// \@bpnodeset \c bpnodeset_name, but the \c bpnodeset_name may be empty. + /// + /// The first line of the section contains the names of the maps separated + /// with white spaces. Each next lines describes a node in the nodeset, and + /// contains the mapped values for each map. + /// + /// If the nodeset contains an \c "label" named map then it will be regarded + /// as label map. This map should contain only unique values and when the + /// \c writeLabel() member will be called with a node it will write it's + /// label. Otherwise if the \c _forceLabelMap constructor parameter is true + /// then the label map will be the id in the graph. In addition if the + /// the \c _forceSort is true then the writer will write the edges + /// sorted by the labels. + /// + /// \relates LemonWriter + template + class BpNodeSetWriter : public LemonWriter::SectionWriter { + typedef LemonWriter::SectionWriter Parent; + public: + + typedef _Graph Graph; + typedef _Traits Traits; + typedef typename Graph::Node Node; + + /// \brief Constructor. + /// + /// Constructor for BpNodeSetWriter. It creates the BpNodeSetWriter and + /// attach it into the given LemonWriter. If the \c _forceLabelMap + /// parameter is true then the writer will write own label map when + /// the user does not give "label" named map. In addition if the + /// the \c _forceSort is true then the writer will write the nodes + /// sorted by the labels. + BpNodeSetWriter(LemonWriter& _writer, const Graph& _graph, + const std::string& _name = std::string(), + bool _forceLabelMap = true, bool _forceSort = true) + : Parent(_writer), labelMap(0), forceLabelMap(_forceLabelMap), + forceSort(_forceSort), graph(_graph), name(_name) {} + + /// \brief Destructor. + /// + /// Destructor for BpNodeSetWriter. + virtual ~BpNodeSetWriter() { + typename MapWriters::iterator it; + for (it = writers.begin(); it != writers.end(); ++it) { + delete it->second; + } + } + + private: + BpNodeSetWriter(const BpNodeSetWriter&); + void operator=(const BpNodeSetWriter&); + + public: + + /// \brief Add a new A-node map writer command for the writer. + /// + /// Add a new A-node map writer command for the writer. + template + BpNodeSetWriter& writeANodeMap(std::string label, const Map& map) { + return writeANodeMap, Map>(label, map); + } + + /// \brief Add a new A-node map writer command for the writer. + /// + /// Add a new A-node map writer command for the writer. + template + BpNodeSetWriter& writeANodeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + if (label == "label") { + throw IoParameterError("Label cannot be A-node map"); + } + awriters.push_back(make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + /// \brief Add a new B-node map writer command for the writer. + /// + /// Add a new B-node map writer command for the writer. + template + BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map) { + return writeBNodeMap, Map>(label, map); + } + + /// \brief Add a new B-node map writer command for the writer. + /// + /// Add a new B-node map writer command for the writer. + template + BpNodeSetWriter& writeBNodeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + if (label == "label") { + throw IoParameterError("Label cannot be B-node map"); + } + bwriters.push_back(make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + BpNodeSetWriter& writeNodeMap(std::string label, const Map& map) { + return writeNodeMap, Map>(label, map); + } + + /// \brief Add a new node map writer command for the writer. + /// + /// Add a new node map writer command for the writer. + template + BpNodeSetWriter& writeNodeMap(std::string label, const Map& map, + const ItemWriter& iw = ItemWriter()) { + checkConcept, Map>(); + checkConcept<_writer_bits::ItemWriter,ItemWriter>(); + writers.push_back(make_pair(label, new _writer_bits:: + MapWriter(map, iw))); + return *this; + } + + protected: + + /// \brief The header of the section. + /// + /// It gives back the header of the section. + virtual std::string header() { + return "@bpnodeset " + name; + } + + /// \brief Writer function of the section. + /// + /// Write the content of the section. + virtual void write(std::ostream& os) { + for (int i = 0; i < int(writers.size()); ++i) { + if (writers[i].first == "label") { + labelMap = writers[i].second; + forceLabelMap = false; + break; + } + } + { + os << "&anodeset "; + std::vector items; + for (typename Graph::ANodeIt it(graph); it != INVALID; ++it) { + items.push_back(it); + } + if (forceSort) { + if (labelMap) { + labelMap->sort(items); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(items.begin(), items.end(), less); + } + } + if (forceLabelMap) { + os << "label\t"; + } + for (int i = 0; i < int(writers.size()); ++i) { + os << writers[i].first << '\t'; + } + for (int i = 0; i < int(awriters.size()); ++i) { + os << awriters[i].first << '\t'; + } + os << std::endl; + for (typename std::vector::iterator it = items.begin(); + it != items.end(); ++it) { + if (forceLabelMap) { + os << graph.id(*it) << '\t'; + } + for (int i = 0; i < int(writers.size()); ++i) { + writers[i].second->write(os, *it); + os << '\t'; + } + for (int i = 0; i < int(awriters.size()); ++i) { + awriters[i].second->write(os, *it); + os << '\t'; + } + os << std::endl; + } + } + { + os << "&bnodeset "; + std::vector items; + for (typename Graph::BNodeIt it(graph); it != INVALID; ++it) { + items.push_back(it); + } + if (forceSort) { + if (labelMap) { + labelMap->sort(items); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(items.begin(), items.end(), less); + } + } + if (forceLabelMap) { + os << "label\t"; + } + for (int i = 0; i < int(writers.size()); ++i) { + os << writers[i].first << '\t'; + } + for (int i = 0; i < int(bwriters.size()); ++i) { + os << bwriters[i].first << '\t'; + } + os << std::endl; + for (typename std::vector::iterator it = items.begin(); + it != items.end(); ++it) { + if (forceLabelMap) { + os << graph.id(*it) << '\t'; + } + for (int i = 0; i < int(writers.size()); ++i) { + writers[i].second->write(os, *it); + os << '\t'; + } + for (int i = 0; i < int(bwriters.size()); ++i) { + bwriters[i].second->write(os, *it); + os << '\t'; + } + os << std::endl; + } + } + } + + public: + + /// \brief Returns true if the nodeset can write the labels of the nodes. + /// + /// Returns true if the nodeset can write the labels of the nodes. + /// It is possible only if a "label" named map was written or the + /// \c _forceLabelMap constructor parameter was true. + bool isLabelWriter() const { + return labelMap != 0 || forceLabelMap; + } + + /// \brief Write the label of the given node. + /// + /// It writes the label of the given node. If there was written a "label" + /// named map then it will write the map value belongs to the node. + /// Otherwise if the \c forceLabel parameter was true it will write + /// its label in the graph. + void writeLabel(std::ostream& os, const Node& item) const { + if (forceLabelMap) { + os << graph.id(item); + } else { + labelMap->write(os, item); + } + } + + /// \brief Sorts the given node vector by label. + /// + /// Sorts the given node vector by label. If there was written an + /// "label" named map then the vector will be sorted by the values + /// of this map. Otherwise if the \c forceLabel parameter was true + /// it will be sorted by its id in the graph. + void sortByLabel(std::vector& nodes) const { + if (labelMap) { + labelMap->sort(nodes); + } else { + typedef IdMap Map; + Map map(graph); + _writer_bits::ComposeLess less(map); + std::sort(nodes.begin(), nodes.end(), less); + } + } + + private: + + typedef std::vector*> > MapWriters; + MapWriters awriters, bwriters, writers; + + _writer_bits::MapWriterBase* labelMap; + bool forceLabelMap; + bool forceSort; + + const Graph& graph; + std::string name; + + }; + + /// \ingroup section_io /// \brief SectionWriter for writing a graph's edgesets. /// /// The lemon format can store multiple graph edgesets with several maps.