lemon/lemon_writer.h
changeset 2502 9c23c3762bc5
parent 2467 2025a571895e
child 2553 bfced05fa852
     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.