COIN-OR::LEMON - Graph Library

Ticket #69: 008af84a4d4a.patch

File 008af84a4d4a.patch, 64.1 KB (added by Balazs Dezso, 14 years ago)

LGF reader and writer for bipartite graphs

  • doc/lgf.dox

    # HG changeset patch
    # User Balazs Dezso <deba@inf.elte.hu>
    # Date 1290721529 -3600
    # Node ID 008af84a4d4af8ab0898ba29bd8c07cceda12e3b
    # Parent  41a2fc90ece074af5d01218bc33bcd66eff08642
    LGF reader and writer for bipartite graphs
    
    diff -r 41a2fc90ece0 -r 008af84a4d4a doc/lgf.dox
    a b  
    6363 3      (40,10)      10      "Third node"
    6464\endcode
    6565
     66The \e LGF files can also contain bipartite graphs, in this case a
     67\c @red_nodes and a \c @blue_nodes sections describe the node set of the
     68graph. If a map is in both of these sections, then it can be used as a
     69regular node map.
     70
     71\code
     72 @red_nodes
     73 label  only_red_map   name
     74 1      "cherry"       "John"
     75 2      "Santa Claus"  "Jack"
     76 3      "blood"        "Jason"
     77 @blue_nodes
     78 label  name
     79 4      "Elisabeth"
     80 5      "Eve"
     81\endcode
     82
    6683The \c \@arcs section is very similar to the \c \@nodes section,
    6784it again starts with a header line describing the names of the maps,
    6885but the \c "label" map is not obligatory here. The following lines
  • lemon/full_graph.h

    diff -r 41a2fc90ece0 -r 008af84a4d4a lemon/full_graph.h
    a b  
    991991      Parent::notifier(Arc()).build();
    992992    }
    993993
     994    using Parent::redNode;
     995    using Parent::blueNode;
     996
    994997    /// \brief Returns the red node with the given index.
    995998    ///
    996999    /// Returns the red node with the given index. Since this
  • lemon/lgf_reader.h

    diff -r 41a2fc90ece0 -r 008af84a4d4a lemon/lgf_reader.h
    a b  
    21142114    return tmp;
    21152115  }
    21162116
     2117  template <typename BGR>
     2118  class BpGraphReader;
     2119
     2120  template <typename TBGR>
     2121  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is = std::cin);
     2122  template <typename TBGR>
     2123  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn);
     2124  template <typename TBGR>
     2125  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
     2126
     2127  /// \ingroup lemon_io
     2128  ///
     2129  /// \brief \ref lgf-format "LGF" reader for bipartite graphs
     2130  ///
     2131  /// This utility reads an \ref lgf-format "LGF" file.
     2132  ///
     2133  /// It can be used almost the same way as \c GraphReader, but it
     2134  /// reads the red and blue nodes from separate sections, and these
     2135  /// sections can contain different set of maps.
     2136  ///
     2137  /// The red and blue maps are read from the corresponding
     2138  /// sections. If a map is defined with the same name in both of
     2139  /// these sections, then it can be read as a node map.
     2140  template <typename BGR>
     2141  class BpGraphReader {
     2142  public:
     2143
     2144    typedef BGR Graph;
     2145
     2146  private:
     2147
     2148    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
     2149
     2150    std::istream* _is;
     2151    bool local_is;
     2152    std::string _filename;
     2153
     2154    BGR& _graph;
     2155
     2156    std::string _nodes_caption;
     2157    std::string _edges_caption;
     2158    std::string _attributes_caption;
     2159
     2160    typedef std::map<std::string, Node> NodeIndex;
     2161    NodeIndex _node_index;
     2162    typedef std::map<std::string, Edge> EdgeIndex;
     2163    EdgeIndex _edge_index;
     2164
     2165    typedef std::vector<std::pair<std::string,
     2166      _reader_bits::MapStorageBase<Node>*> > NodeMaps;
     2167    NodeMaps _red_maps;
     2168    NodeMaps _blue_maps;
     2169
     2170    typedef std::vector<std::pair<std::string,
     2171      _reader_bits::MapStorageBase<Edge>*> > EdgeMaps;
     2172    EdgeMaps _edge_maps;
     2173
     2174    typedef std::multimap<std::string, _reader_bits::ValueStorageBase*>
     2175      Attributes;
     2176    Attributes _attributes;
     2177
     2178    bool _use_nodes;
     2179    bool _use_edges;
     2180
     2181    bool _skip_nodes;
     2182    bool _skip_edges;
     2183
     2184    int line_num;
     2185    std::istringstream line;
     2186
     2187  public:
     2188
     2189    /// \brief Constructor
     2190    ///
     2191    /// Construct an undirected graph reader, which reads from the given
     2192    /// input stream.
     2193    BpGraphReader(BGR& graph, std::istream& is = std::cin)
     2194      : _is(&is), local_is(false), _graph(graph),
     2195        _use_nodes(false), _use_edges(false),
     2196        _skip_nodes(false), _skip_edges(false) {}
     2197
     2198    /// \brief Constructor
     2199    ///
     2200    /// Construct an undirected graph reader, which reads from the given
     2201    /// file.
     2202    BpGraphReader(BGR& graph, const std::string& fn)
     2203      : _is(new std::ifstream(fn.c_str())), local_is(true),
     2204        _filename(fn), _graph(graph),
     2205        _use_nodes(false), _use_edges(false),
     2206        _skip_nodes(false), _skip_edges(false) {
     2207      if (!(*_is)) {
     2208        delete _is;
     2209        throw IoError("Cannot open file", fn);
     2210      }
     2211    }
     2212
     2213    /// \brief Constructor
     2214    ///
     2215    /// Construct an undirected graph reader, which reads from the given
     2216    /// file.
     2217    BpGraphReader(BGR& graph, const char* fn)
     2218      : _is(new std::ifstream(fn)), local_is(true),
     2219        _filename(fn), _graph(graph),
     2220        _use_nodes(false), _use_edges(false),
     2221        _skip_nodes(false), _skip_edges(false) {
     2222      if (!(*_is)) {
     2223        delete _is;
     2224        throw IoError("Cannot open file", fn);
     2225      }
     2226    }
     2227
     2228    /// \brief Destructor
     2229    ~BpGraphReader() {
     2230      for (typename NodeMaps::iterator it = _red_maps.begin();
     2231           it != _red_maps.end(); ++it) {
     2232        delete it->second;
     2233      }
     2234
     2235      for (typename NodeMaps::iterator it = _blue_maps.begin();
     2236           it != _blue_maps.end(); ++it) {
     2237        delete it->second;
     2238      }
     2239
     2240      for (typename EdgeMaps::iterator it = _edge_maps.begin();
     2241           it != _edge_maps.end(); ++it) {
     2242        delete it->second;
     2243      }
     2244
     2245      for (typename Attributes::iterator it = _attributes.begin();
     2246           it != _attributes.end(); ++it) {
     2247        delete it->second;
     2248      }
     2249
     2250      if (local_is) {
     2251        delete _is;
     2252      }
     2253
     2254    }
     2255
     2256  private:
     2257    template <typename TBGR>
     2258    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is);
     2259    template <typename TBGR>
     2260    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph,
     2261                                             const std::string& fn);
     2262    template <typename TBGR>
     2263    friend BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char *fn);
     2264
     2265    BpGraphReader(BpGraphReader& other)
     2266      : _is(other._is), local_is(other.local_is), _graph(other._graph),
     2267        _use_nodes(other._use_nodes), _use_edges(other._use_edges),
     2268        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
     2269
     2270      other._is = 0;
     2271      other.local_is = false;
     2272
     2273      _node_index.swap(other._node_index);
     2274      _edge_index.swap(other._edge_index);
     2275
     2276      _red_maps.swap(other._red_maps);
     2277      _blue_maps.swap(other._blue_maps);
     2278      _edge_maps.swap(other._edge_maps);
     2279      _attributes.swap(other._attributes);
     2280
     2281      _nodes_caption = other._nodes_caption;
     2282      _edges_caption = other._edges_caption;
     2283      _attributes_caption = other._attributes_caption;
     2284
     2285    }
     2286
     2287    BpGraphReader& operator=(const BpGraphReader&);
     2288
     2289  public:
     2290
     2291    /// \name Reading Rules
     2292    /// @{
     2293
     2294    /// \brief Node map reading rule
     2295    ///
     2296    /// Add a node map reading rule to the reader.
     2297    template <typename Map>
     2298    BpGraphReader& nodeMap(const std::string& caption, Map& map) {
     2299      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2300      _reader_bits::MapStorageBase<Node>* red_storage =
     2301        new _reader_bits::MapStorage<Node, Map>(map);
     2302      _red_maps.push_back(std::make_pair(caption, red_storage));
     2303      _reader_bits::MapStorageBase<Node>* blue_storage =
     2304        new _reader_bits::MapStorage<Node, Map>(map);
     2305      _blue_maps.push_back(std::make_pair(caption, blue_storage));
     2306      return *this;
     2307    }
     2308
     2309    /// \brief Node map reading rule
     2310    ///
     2311    /// Add a node map reading rule with specialized converter to the
     2312    /// reader.
     2313    template <typename Map, typename Converter>
     2314    BpGraphReader& nodeMap(const std::string& caption, Map& map,
     2315                           const Converter& converter = Converter()) {
     2316      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2317      _reader_bits::MapStorageBase<Node>* red_storage =
     2318        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
     2319      _red_maps.push_back(std::make_pair(caption, red_storage));
     2320      _reader_bits::MapStorageBase<Node>* blue_storage =
     2321        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
     2322      _blue_maps.push_back(std::make_pair(caption, blue_storage));
     2323      return *this;
     2324    }
     2325
     2326    /// Add a red map reading rule to the reader.
     2327    template <typename Map>
     2328    BpGraphReader& redMap(const std::string& caption, Map& map) {
     2329      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2330      _reader_bits::MapStorageBase<Node>* storage =
     2331        new _reader_bits::MapStorage<Node, Map>(map);
     2332      _red_maps.push_back(std::make_pair(caption, storage));
     2333      return *this;
     2334    }
     2335
     2336    /// \brief Red map reading rule
     2337    ///
     2338    /// Add a red map reading rule with specialized converter to the
     2339    /// reader.
     2340    template <typename Map, typename Converter>
     2341    BpGraphReader& redMap(const std::string& caption, Map& map,
     2342                          const Converter& converter = Converter()) {
     2343      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2344      _reader_bits::MapStorageBase<Node>* storage =
     2345        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
     2346      _red_maps.push_back(std::make_pair(caption, storage));
     2347      return *this;
     2348    }
     2349
     2350    /// Add a blue map reading rule to the reader.
     2351    template <typename Map>
     2352    BpGraphReader& blueMap(const std::string& caption, Map& map) {
     2353      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2354      _reader_bits::MapStorageBase<Node>* storage =
     2355        new _reader_bits::MapStorage<Node, Map>(map);
     2356      _blue_maps.push_back(std::make_pair(caption, storage));
     2357      return *this;
     2358    }
     2359
     2360    /// \brief Blue map reading rule
     2361    ///
     2362    /// Add a blue map reading rule with specialized converter to the
     2363    /// reader.
     2364    template <typename Map, typename Converter>
     2365    BpGraphReader& blueMap(const std::string& caption, Map& map,
     2366                           const Converter& converter = Converter()) {
     2367      checkConcept<concepts::WriteMap<Node, typename Map::Value>, Map>();
     2368      _reader_bits::MapStorageBase<Node>* storage =
     2369        new _reader_bits::MapStorage<Node, Map, Converter>(map, converter);
     2370      _blue_maps.push_back(std::make_pair(caption, storage));
     2371      return *this;
     2372    }
     2373
     2374    /// \brief Edge map reading rule
     2375    ///
     2376    /// Add an edge map reading rule to the reader.
     2377    template <typename Map>
     2378    BpGraphReader& edgeMap(const std::string& caption, Map& map) {
     2379      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
     2380      _reader_bits::MapStorageBase<Edge>* storage =
     2381        new _reader_bits::MapStorage<Edge, Map>(map);
     2382      _edge_maps.push_back(std::make_pair(caption, storage));
     2383      return *this;
     2384    }
     2385
     2386    /// \brief Edge map reading rule
     2387    ///
     2388    /// Add an edge map reading rule with specialized converter to the
     2389    /// reader.
     2390    template <typename Map, typename Converter>
     2391    BpGraphReader& edgeMap(const std::string& caption, Map& map,
     2392                          const Converter& converter = Converter()) {
     2393      checkConcept<concepts::WriteMap<Edge, typename Map::Value>, Map>();
     2394      _reader_bits::MapStorageBase<Edge>* storage =
     2395        new _reader_bits::MapStorage<Edge, Map, Converter>(map, converter);
     2396      _edge_maps.push_back(std::make_pair(caption, storage));
     2397      return *this;
     2398    }
     2399
     2400    /// \brief Arc map reading rule
     2401    ///
     2402    /// Add an arc map reading rule to the reader.
     2403    template <typename Map>
     2404    BpGraphReader& arcMap(const std::string& caption, Map& map) {
     2405      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
     2406      _reader_bits::MapStorageBase<Edge>* forward_storage =
     2407        new _reader_bits::GraphArcMapStorage<Graph, true, Map>(_graph, map);
     2408      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
     2409      _reader_bits::MapStorageBase<Edge>* backward_storage =
     2410        new _reader_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
     2411      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
     2412      return *this;
     2413    }
     2414
     2415    /// \brief Arc map reading rule
     2416    ///
     2417    /// Add an arc map reading rule with specialized converter to the
     2418    /// reader.
     2419    template <typename Map, typename Converter>
     2420    BpGraphReader& arcMap(const std::string& caption, Map& map,
     2421                          const Converter& converter = Converter()) {
     2422      checkConcept<concepts::WriteMap<Arc, typename Map::Value>, Map>();
     2423      _reader_bits::MapStorageBase<Edge>* forward_storage =
     2424        new _reader_bits::GraphArcMapStorage<BGR, true, Map, Converter>
     2425        (_graph, map, converter);
     2426      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
     2427      _reader_bits::MapStorageBase<Edge>* backward_storage =
     2428        new _reader_bits::GraphArcMapStorage<BGR, false, Map, Converter>
     2429        (_graph, map, converter);
     2430      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
     2431      return *this;
     2432    }
     2433
     2434    /// \brief Attribute reading rule
     2435    ///
     2436    /// Add an attribute reading rule to the reader.
     2437    template <typename Value>
     2438    BpGraphReader& attribute(const std::string& caption, Value& value) {
     2439      _reader_bits::ValueStorageBase* storage =
     2440        new _reader_bits::ValueStorage<Value>(value);
     2441      _attributes.insert(std::make_pair(caption, storage));
     2442      return *this;
     2443    }
     2444
     2445    /// \brief Attribute reading rule
     2446    ///
     2447    /// Add an attribute reading rule with specialized converter to the
     2448    /// reader.
     2449    template <typename Value, typename Converter>
     2450    BpGraphReader& attribute(const std::string& caption, Value& value,
     2451                             const Converter& converter = Converter()) {
     2452      _reader_bits::ValueStorageBase* storage =
     2453        new _reader_bits::ValueStorage<Value, Converter>(value, converter);
     2454      _attributes.insert(std::make_pair(caption, storage));
     2455      return *this;
     2456    }
     2457
     2458    /// \brief Node reading rule
     2459    ///
     2460    /// Add a node reading rule to reader.
     2461    BpGraphReader& node(const std::string& caption, Node& node) {
     2462      typedef _reader_bits::MapLookUpConverter<Node> Converter;
     2463      Converter converter(_node_index);
     2464      _reader_bits::ValueStorageBase* storage =
     2465        new _reader_bits::ValueStorage<Node, Converter>(node, converter);
     2466      _attributes.insert(std::make_pair(caption, storage));
     2467      return *this;
     2468    }
     2469
     2470    /// \brief Edge reading rule
     2471    ///
     2472    /// Add an edge reading rule to reader.
     2473    BpGraphReader& edge(const std::string& caption, Edge& edge) {
     2474      typedef _reader_bits::MapLookUpConverter<Edge> Converter;
     2475      Converter converter(_edge_index);
     2476      _reader_bits::ValueStorageBase* storage =
     2477        new _reader_bits::ValueStorage<Edge, Converter>(edge, converter);
     2478      _attributes.insert(std::make_pair(caption, storage));
     2479      return *this;
     2480    }
     2481
     2482    /// \brief Arc reading rule
     2483    ///
     2484    /// Add an arc reading rule to reader.
     2485    BpGraphReader& arc(const std::string& caption, Arc& arc) {
     2486      typedef _reader_bits::GraphArcLookUpConverter<BGR> Converter;
     2487      Converter converter(_graph, _edge_index);
     2488      _reader_bits::ValueStorageBase* storage =
     2489        new _reader_bits::ValueStorage<Arc, Converter>(arc, converter);
     2490      _attributes.insert(std::make_pair(caption, storage));
     2491      return *this;
     2492    }
     2493
     2494    /// @}
     2495
     2496    /// \name Select Section by Name
     2497    /// @{
     2498
     2499    /// \brief Set \c \@nodes section to be read
     2500    ///
     2501    /// Set \c \@nodes section to be read.
     2502    BpGraphReader& nodes(const std::string& caption) {
     2503      _nodes_caption = caption;
     2504      return *this;
     2505    }
     2506
     2507    /// \brief Set \c \@edges section to be read
     2508    ///
     2509    /// Set \c \@edges section to be read.
     2510    BpGraphReader& edges(const std::string& caption) {
     2511      _edges_caption = caption;
     2512      return *this;
     2513    }
     2514
     2515    /// \brief Set \c \@attributes section to be read
     2516    ///
     2517    /// Set \c \@attributes section to be read.
     2518    BpGraphReader& attributes(const std::string& caption) {
     2519      _attributes_caption = caption;
     2520      return *this;
     2521    }
     2522
     2523    /// @}
     2524
     2525    /// \name Using Previously Constructed Node or Edge Set
     2526    /// @{
     2527
     2528    /// \brief Use previously constructed node set
     2529    ///
     2530    /// Use previously constructed node set, and specify the node
     2531    /// label map.
     2532    template <typename Map>
     2533    BpGraphReader& useNodes(const Map& map) {
     2534      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     2535      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
     2536      _use_nodes = true;
     2537      _writer_bits::DefaultConverter<typename Map::Value> converter;
     2538      for (NodeIt n(_graph); n != INVALID; ++n) {
     2539        _node_index.insert(std::make_pair(converter(map[n]), n));
     2540      }
     2541      return *this;
     2542    }
     2543
     2544    /// \brief Use previously constructed node set
     2545    ///
     2546    /// Use previously constructed node set, and specify the node
     2547    /// label map and a functor which converts the label map values to
     2548    /// \c std::string.
     2549    template <typename Map, typename Converter>
     2550    BpGraphReader& useNodes(const Map& map,
     2551                            const Converter& converter = Converter()) {
     2552      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     2553      LEMON_ASSERT(!_use_nodes, "Multiple usage of useNodes() member");
     2554      _use_nodes = true;
     2555      for (NodeIt n(_graph); n != INVALID; ++n) {
     2556        _node_index.insert(std::make_pair(converter(map[n]), n));
     2557      }
     2558      return *this;
     2559    }
     2560
     2561    /// \brief Use previously constructed edge set
     2562    ///
     2563    /// Use previously constructed edge set, and specify the edge
     2564    /// label map.
     2565    template <typename Map>
     2566    BpGraphReader& useEdges(const Map& map) {
     2567      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
     2568      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
     2569      _use_edges = true;
     2570      _writer_bits::DefaultConverter<typename Map::Value> converter;
     2571      for (EdgeIt a(_graph); a != INVALID; ++a) {
     2572        _edge_index.insert(std::make_pair(converter(map[a]), a));
     2573      }
     2574      return *this;
     2575    }
     2576
     2577    /// \brief Use previously constructed edge set
     2578    ///
     2579    /// Use previously constructed edge set, and specify the edge
     2580    /// label map and a functor which converts the label map values to
     2581    /// \c std::string.
     2582    template <typename Map, typename Converter>
     2583    BpGraphReader& useEdges(const Map& map,
     2584                            const Converter& converter = Converter()) {
     2585      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
     2586      LEMON_ASSERT(!_use_edges, "Multiple usage of useEdges() member");
     2587      _use_edges = true;
     2588      for (EdgeIt a(_graph); a != INVALID; ++a) {
     2589        _edge_index.insert(std::make_pair(converter(map[a]), a));
     2590      }
     2591      return *this;
     2592    }
     2593
     2594    /// \brief Skip the reading of node section
     2595    ///
     2596    /// Omit the reading of the node section. This implies that each node
     2597    /// map reading rule will be abandoned, and the nodes of the graph
     2598    /// will not be constructed, which usually cause that the edge set
     2599    /// could not be read due to lack of node name
     2600    /// could not be read due to lack of node name resolving.
     2601    /// Therefore \c skipEdges() function should also be used, or
     2602    /// \c useNodes() should be used to specify the label of the nodes.
     2603    BpGraphReader& skipNodes() {
     2604      LEMON_ASSERT(!_skip_nodes, "Skip nodes already set");
     2605      _skip_nodes = true;
     2606      return *this;
     2607    }
     2608
     2609    /// \brief Skip the reading of edge section
     2610    ///
     2611    /// Omit the reading of the edge section. This implies that each edge
     2612    /// map reading rule will be abandoned, and the edges of the graph
     2613    /// will not be constructed.
     2614    BpGraphReader& skipEdges() {
     2615      LEMON_ASSERT(!_skip_edges, "Skip edges already set");
     2616      _skip_edges = true;
     2617      return *this;
     2618    }
     2619
     2620    /// @}
     2621
     2622  private:
     2623
     2624    bool readLine() {
     2625      std::string str;
     2626      while(++line_num, std::getline(*_is, str)) {
     2627        line.clear(); line.str(str);
     2628        char c;
     2629        if (line >> std::ws >> c && c != '#') {
     2630          line.putback(c);
     2631          return true;
     2632        }
     2633      }
     2634      return false;
     2635    }
     2636
     2637    bool readSuccess() {
     2638      return static_cast<bool>(*_is);
     2639    }
     2640
     2641    void skipSection() {
     2642      char c;
     2643      while (readSuccess() && line >> c && c != '@') {
     2644        readLine();
     2645      }
     2646      if (readSuccess()) {
     2647        line.putback(c);
     2648      }
     2649    }
     2650
     2651    void readRedNodes() {
     2652
     2653      std::vector<int> map_index(_red_maps.size());
     2654      int map_num, label_index;
     2655
     2656      char c;
     2657      if (!readLine() || !(line >> c) || c == '@') {
     2658        if (readSuccess() && line) line.putback(c);
     2659        if (!_red_maps.empty())
     2660          throw FormatError("Cannot find map names");
     2661        return;
     2662      }
     2663      line.putback(c);
     2664
     2665      {
     2666        std::map<std::string, int> maps;
     2667
     2668        std::string map;
     2669        int index = 0;
     2670        while (_reader_bits::readToken(line, map)) {
     2671          if (maps.find(map) != maps.end()) {
     2672            std::ostringstream msg;
     2673            msg << "Multiple occurence of red map: " << map;
     2674            throw FormatError(msg.str());
     2675          }
     2676          maps.insert(std::make_pair(map, index));
     2677          ++index;
     2678        }
     2679
     2680        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
     2681          std::map<std::string, int>::iterator jt =
     2682            maps.find(_red_maps[i].first);
     2683          if (jt == maps.end()) {
     2684            std::ostringstream msg;
     2685            msg << "Map not found: " << _red_maps[i].first;
     2686            throw FormatError(msg.str());
     2687          }
     2688          map_index[i] = jt->second;
     2689        }
     2690
     2691        {
     2692          std::map<std::string, int>::iterator jt = maps.find("label");
     2693          if (jt != maps.end()) {
     2694            label_index = jt->second;
     2695          } else {
     2696            label_index = -1;
     2697          }
     2698        }
     2699        map_num = maps.size();
     2700      }
     2701
     2702      while (readLine() && line >> c && c != '@') {
     2703        line.putback(c);
     2704
     2705        std::vector<std::string> tokens(map_num);
     2706        for (int i = 0; i < map_num; ++i) {
     2707          if (!_reader_bits::readToken(line, tokens[i])) {
     2708            std::ostringstream msg;
     2709            msg << "Column not found (" << i + 1 << ")";
     2710            throw FormatError(msg.str());
     2711          }
     2712        }
     2713        if (line >> std::ws >> c)
     2714          throw FormatError("Extra character at the end of line");
     2715
     2716        Node n;
     2717        if (!_use_nodes) {
     2718          n = _graph.addRedNode();
     2719          if (label_index != -1)
     2720            _node_index.insert(std::make_pair(tokens[label_index], n));
     2721        } else {
     2722          if (label_index == -1)
     2723            throw FormatError("Label map not found");
     2724          typename std::map<std::string, Node>::iterator it =
     2725            _node_index.find(tokens[label_index]);
     2726          if (it == _node_index.end()) {
     2727            std::ostringstream msg;
     2728            msg << "Node with label not found: " << tokens[label_index];
     2729            throw FormatError(msg.str());
     2730          }
     2731          n = it->second;
     2732        }
     2733
     2734        for (int i = 0; i < static_cast<int>(_red_maps.size()); ++i) {
     2735          _red_maps[i].second->set(n, tokens[map_index[i]]);
     2736        }
     2737
     2738      }
     2739      if (readSuccess()) {
     2740        line.putback(c);
     2741      }
     2742    }
     2743
     2744    void readBlueNodes() {
     2745
     2746      std::vector<int> map_index(_blue_maps.size());
     2747      int map_num, label_index;
     2748
     2749      char c;
     2750      if (!readLine() || !(line >> c) || c == '@') {
     2751        if (readSuccess() && line) line.putback(c);
     2752        if (!_blue_maps.empty())
     2753          throw FormatError("Cannot find map names");
     2754        return;
     2755      }
     2756      line.putback(c);
     2757
     2758      {
     2759        std::map<std::string, int> maps;
     2760
     2761        std::string map;
     2762        int index = 0;
     2763        while (_reader_bits::readToken(line, map)) {
     2764          if (maps.find(map) != maps.end()) {
     2765            std::ostringstream msg;
     2766            msg << "Multiple occurence of blue map: " << map;
     2767            throw FormatError(msg.str());
     2768          }
     2769          maps.insert(std::make_pair(map, index));
     2770          ++index;
     2771        }
     2772
     2773        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
     2774          std::map<std::string, int>::iterator jt =
     2775            maps.find(_blue_maps[i].first);
     2776          if (jt == maps.end()) {
     2777            std::ostringstream msg;
     2778            msg << "Map not found: " << _blue_maps[i].first;
     2779            throw FormatError(msg.str());
     2780          }
     2781          map_index[i] = jt->second;
     2782        }
     2783
     2784        {
     2785          std::map<std::string, int>::iterator jt = maps.find("label");
     2786          if (jt != maps.end()) {
     2787            label_index = jt->second;
     2788          } else {
     2789            label_index = -1;
     2790          }
     2791        }
     2792        map_num = maps.size();
     2793      }
     2794
     2795      while (readLine() && line >> c && c != '@') {
     2796        line.putback(c);
     2797
     2798        std::vector<std::string> tokens(map_num);
     2799        for (int i = 0; i < map_num; ++i) {
     2800          if (!_reader_bits::readToken(line, tokens[i])) {
     2801            std::ostringstream msg;
     2802            msg << "Column not found (" << i + 1 << ")";
     2803            throw FormatError(msg.str());
     2804          }
     2805        }
     2806        if (line >> std::ws >> c)
     2807          throw FormatError("Extra character at the end of line");
     2808
     2809        Node n;
     2810        if (!_use_nodes) {
     2811          n = _graph.addBlueNode();
     2812          if (label_index != -1)
     2813            _node_index.insert(std::make_pair(tokens[label_index], n));
     2814        } else {
     2815          if (label_index == -1)
     2816            throw FormatError("Label map not found");
     2817          typename std::map<std::string, Node>::iterator it =
     2818            _node_index.find(tokens[label_index]);
     2819          if (it == _node_index.end()) {
     2820            std::ostringstream msg;
     2821            msg << "Node with label not found: " << tokens[label_index];
     2822            throw FormatError(msg.str());
     2823          }
     2824          n = it->second;
     2825        }
     2826
     2827        for (int i = 0; i < static_cast<int>(_blue_maps.size()); ++i) {
     2828          _blue_maps[i].second->set(n, tokens[map_index[i]]);
     2829        }
     2830
     2831      }
     2832      if (readSuccess()) {
     2833        line.putback(c);
     2834      }
     2835    }
     2836
     2837    void readEdges() {
     2838
     2839      std::vector<int> map_index(_edge_maps.size());
     2840      int map_num, label_index;
     2841
     2842      char c;
     2843      if (!readLine() || !(line >> c) || c == '@') {
     2844        if (readSuccess() && line) line.putback(c);
     2845        if (!_edge_maps.empty())
     2846          throw FormatError("Cannot find map names");
     2847        return;
     2848      }
     2849      line.putback(c);
     2850
     2851      {
     2852        std::map<std::string, int> maps;
     2853
     2854        std::string map;
     2855        int index = 0;
     2856        while (_reader_bits::readToken(line, map)) {
     2857          if (maps.find(map) != maps.end()) {
     2858            std::ostringstream msg;
     2859            msg << "Multiple occurence of edge map: " << map;
     2860            throw FormatError(msg.str());
     2861          }
     2862          maps.insert(std::make_pair(map, index));
     2863          ++index;
     2864        }
     2865
     2866        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
     2867          std::map<std::string, int>::iterator jt =
     2868            maps.find(_edge_maps[i].first);
     2869          if (jt == maps.end()) {
     2870            std::ostringstream msg;
     2871            msg << "Map not found: " << _edge_maps[i].first;
     2872            throw FormatError(msg.str());
     2873          }
     2874          map_index[i] = jt->second;
     2875        }
     2876
     2877        {
     2878          std::map<std::string, int>::iterator jt = maps.find("label");
     2879          if (jt != maps.end()) {
     2880            label_index = jt->second;
     2881          } else {
     2882            label_index = -1;
     2883          }
     2884        }
     2885        map_num = maps.size();
     2886      }
     2887
     2888      while (readLine() && line >> c && c != '@') {
     2889        line.putback(c);
     2890
     2891        std::string source_token;
     2892        std::string target_token;
     2893
     2894        if (!_reader_bits::readToken(line, source_token))
     2895          throw FormatError("Red node not found");
     2896
     2897        if (!_reader_bits::readToken(line, target_token))
     2898          throw FormatError("Blue node not found");
     2899
     2900        std::vector<std::string> tokens(map_num);
     2901        for (int i = 0; i < map_num; ++i) {
     2902          if (!_reader_bits::readToken(line, tokens[i])) {
     2903            std::ostringstream msg;
     2904            msg << "Column not found (" << i + 1 << ")";
     2905            throw FormatError(msg.str());
     2906          }
     2907        }
     2908        if (line >> std::ws >> c)
     2909          throw FormatError("Extra character at the end of line");
     2910
     2911        Edge e;
     2912        if (!_use_edges) {
     2913
     2914          typename NodeIndex::iterator it;
     2915
     2916          it = _node_index.find(source_token);
     2917          if (it == _node_index.end()) {
     2918            std::ostringstream msg;
     2919            msg << "Item not found: " << source_token;
     2920            throw FormatError(msg.str());
     2921          }
     2922          Node source = it->second;
     2923          if (!_graph.red(source)) {
     2924            std::ostringstream msg;
     2925            msg << "Item is not red node: " << source_token;
     2926            throw FormatError(msg.str());
     2927          }
     2928
     2929          it = _node_index.find(target_token);
     2930          if (it == _node_index.end()) {
     2931            std::ostringstream msg;
     2932            msg << "Item not found: " << target_token;
     2933            throw FormatError(msg.str());
     2934          }
     2935          Node target = it->second;
     2936          if (!_graph.blue(target)) {
     2937            std::ostringstream msg;
     2938            msg << "Item is not red node: " << source_token;
     2939            throw FormatError(msg.str());
     2940          }
     2941
     2942          e = _graph.addEdge(source, target);
     2943          if (label_index != -1)
     2944            _edge_index.insert(std::make_pair(tokens[label_index], e));
     2945        } else {
     2946          if (label_index == -1)
     2947            throw FormatError("Label map not found");
     2948          typename std::map<std::string, Edge>::iterator it =
     2949            _edge_index.find(tokens[label_index]);
     2950          if (it == _edge_index.end()) {
     2951            std::ostringstream msg;
     2952            msg << "Edge with label not found: " << tokens[label_index];
     2953            throw FormatError(msg.str());
     2954          }
     2955          e = it->second;
     2956        }
     2957
     2958        for (int i = 0; i < static_cast<int>(_edge_maps.size()); ++i) {
     2959          _edge_maps[i].second->set(e, tokens[map_index[i]]);
     2960        }
     2961
     2962      }
     2963      if (readSuccess()) {
     2964        line.putback(c);
     2965      }
     2966    }
     2967
     2968    void readAttributes() {
     2969
     2970      std::set<std::string> read_attr;
     2971
     2972      char c;
     2973      while (readLine() && line >> c && c != '@') {
     2974        line.putback(c);
     2975
     2976        std::string attr, token;
     2977        if (!_reader_bits::readToken(line, attr))
     2978          throw FormatError("Attribute name not found");
     2979        if (!_reader_bits::readToken(line, token))
     2980          throw FormatError("Attribute value not found");
     2981        if (line >> c)
     2982          throw FormatError("Extra character at the end of line");
     2983
     2984        {
     2985          std::set<std::string>::iterator it = read_attr.find(attr);
     2986          if (it != read_attr.end()) {
     2987            std::ostringstream msg;
     2988            msg << "Multiple occurence of attribute: " << attr;
     2989            throw FormatError(msg.str());
     2990          }
     2991          read_attr.insert(attr);
     2992        }
     2993
     2994        {
     2995          typename Attributes::iterator it = _attributes.lower_bound(attr);
     2996          while (it != _attributes.end() && it->first == attr) {
     2997            it->second->set(token);
     2998            ++it;
     2999          }
     3000        }
     3001
     3002      }
     3003      if (readSuccess()) {
     3004        line.putback(c);
     3005      }
     3006      for (typename Attributes::iterator it = _attributes.begin();
     3007           it != _attributes.end(); ++it) {
     3008        if (read_attr.find(it->first) == read_attr.end()) {
     3009          std::ostringstream msg;
     3010          msg << "Attribute not found: " << it->first;
     3011          throw FormatError(msg.str());
     3012        }
     3013      }
     3014    }
     3015
     3016  public:
     3017
     3018    /// \name Execution of the Reader
     3019    /// @{
     3020
     3021    /// \brief Start the batch processing
     3022    ///
     3023    /// This function starts the batch processing
     3024    void run() {
     3025
     3026      LEMON_ASSERT(_is != 0, "This reader assigned to an other reader");
     3027
     3028      bool red_nodes_done = _skip_nodes;
     3029      bool blue_nodes_done = _skip_nodes;
     3030      bool edges_done = _skip_edges;
     3031      bool attributes_done = false;
     3032
     3033      line_num = 0;
     3034      readLine();
     3035      skipSection();
     3036
     3037      while (readSuccess()) {
     3038        try {
     3039          char c;
     3040          std::string section, caption;
     3041          line >> c;
     3042          _reader_bits::readToken(line, section);
     3043          _reader_bits::readToken(line, caption);
     3044
     3045          if (line >> c)
     3046            throw FormatError("Extra character at the end of line");
     3047
     3048          if (section == "red_nodes" && !red_nodes_done) {
     3049            if (_nodes_caption.empty() || _nodes_caption == caption) {
     3050              readRedNodes();
     3051              red_nodes_done = true;
     3052            }
     3053          } else if (section == "blue_nodes" && !blue_nodes_done) {
     3054            if (_nodes_caption.empty() || _nodes_caption == caption) {
     3055              readBlueNodes();
     3056              blue_nodes_done = true;
     3057            }
     3058          } else if ((section == "edges" || section == "arcs") &&
     3059                     !edges_done) {
     3060            if (_edges_caption.empty() || _edges_caption == caption) {
     3061              readEdges();
     3062              edges_done = true;
     3063            }
     3064          } else if (section == "attributes" && !attributes_done) {
     3065            if (_attributes_caption.empty() || _attributes_caption == caption) {
     3066              readAttributes();
     3067              attributes_done = true;
     3068            }
     3069          } else {
     3070            readLine();
     3071            skipSection();
     3072          }
     3073        } catch (FormatError& error) {
     3074          error.line(line_num);
     3075          error.file(_filename);
     3076          throw;
     3077        }
     3078      }
     3079
     3080      if (!red_nodes_done) {
     3081        throw FormatError("Section @red_nodes not found");
     3082      }
     3083
     3084      if (!blue_nodes_done) {
     3085        throw FormatError("Section @blue_nodes not found");
     3086      }
     3087
     3088      if (!edges_done) {
     3089        throw FormatError("Section @edges not found");
     3090      }
     3091
     3092      if (!attributes_done && !_attributes.empty()) {
     3093        throw FormatError("Section @attributes not found");
     3094      }
     3095
     3096    }
     3097
     3098    /// @}
     3099
     3100  };
     3101
     3102  /// \ingroup lemon_io
     3103  ///
     3104  /// \brief Return a \ref BpGraphReader class
     3105  ///
     3106  /// This function just returns a \ref BpGraphReader class.
     3107  ///
     3108  /// With this function a graph can be read from an
     3109  /// \ref lgf-format "LGF" file or input stream with several maps and
     3110  /// attributes. For example, there is bipartite weighted matching problem
     3111  /// on a graph, i.e. a graph with a \e weight map on the edges. This
     3112  /// graph can be read with the following code:
     3113  ///
     3114  ///\code
     3115  ///ListBpGraph graph;
     3116  ///ListBpGraph::EdgeMap<int> weight(graph);
     3117  ///bpGraphReader(graph, std::cin).
     3118  ///  edgeMap("weight", weight).
     3119  ///  run();
     3120  ///\endcode
     3121  ///
     3122  /// For a complete documentation, please see the \ref BpGraphReader
     3123  /// class documentation.
     3124  /// \warning Don't forget to put the \ref BpGraphReader::run() "run()"
     3125  /// to the end of the parameter list.
     3126  /// \relates BpGraphReader
     3127  /// \sa bpGraphReader(TBGR& graph, const std::string& fn)
     3128  /// \sa bpGraphReader(TBGR& graph, const char* fn)
     3129  template <typename TBGR>
     3130  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, std::istream& is) {
     3131    BpGraphReader<TBGR> tmp(graph, is);
     3132    return tmp;
     3133  }
     3134
     3135  /// \brief Return a \ref BpGraphReader class
     3136  ///
     3137  /// This function just returns a \ref BpGraphReader class.
     3138  /// \relates BpGraphReader
     3139  /// \sa bpGraphReader(TBGR& graph, std::istream& is)
     3140  template <typename TBGR>
     3141  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const std::string& fn) {
     3142    BpGraphReader<TBGR> tmp(graph, fn);
     3143    return tmp;
     3144  }
     3145
     3146  /// \brief Return a \ref BpGraphReader class
     3147  ///
     3148  /// This function just returns a \ref BpGraphReader class.
     3149  /// \relates BpGraphReader
     3150  /// \sa bpGraphReader(TBGR& graph, std::istream& is)
     3151  template <typename TBGR>
     3152  BpGraphReader<TBGR> bpGraphReader(TBGR& graph, const char* fn) {
     3153    BpGraphReader<TBGR> tmp(graph, fn);
     3154    return tmp;
     3155  }
     3156
    21173157  class SectionReader;
    21183158
    21193159  SectionReader sectionReader(std::istream& is);
  • lemon/lgf_writer.h

    diff -r 41a2fc90ece0 -r 008af84a4d4a lemon/lgf_writer.h
    a b  
    986986
    987987  /// \ingroup lemon_io
    988988  ///
    989   /// \brief \ref lgf-format "LGF" writer for directed graphs
     989  /// \brief \ref lgf-format "LGF" writer for undirected graphs
    990990  ///
    991991  /// This utility writes an \ref lgf-format "LGF" file.
    992992  ///
     
    10421042
    10431043    /// \brief Constructor
    10441044    ///
    1045     /// Construct a directed graph writer, which writes to the given
    1046     /// output stream.
     1045    /// Construct an undirected graph writer, which writes to the
     1046    /// given output stream.
    10471047    GraphWriter(const GR& graph, std::ostream& os = std::cout)
    10481048      : _os(&os), local_os(false), _graph(graph),
    10491049        _skip_nodes(false), _skip_edges(false) {}
    10501050
    10511051    /// \brief Constructor
    10521052    ///
    1053     /// Construct a directed graph writer, which writes to the given
     1053    /// Construct a undirected graph writer, which writes to the given
    10541054    /// output file.
    10551055    GraphWriter(const GR& graph, const std::string& fn)
    10561056      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
     
    10631063
    10641064    /// \brief Constructor
    10651065    ///
    1066     /// Construct a directed graph writer, which writes to the given
     1066    /// Construct a undirected graph writer, which writes to the given
    10671067    /// output file.
    10681068    GraphWriter(const GR& graph, const char* fn)
    10691069      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
     
    12891289      return *this;
    12901290    }
    12911291
    1292     /// \brief Add an additional caption to the \c \@arcs section
     1292    /// \brief Add an additional caption to the \c \@edges section
    12931293    ///
    1294     /// Add an additional caption to the \c \@arcs section.
     1294    /// Add an additional caption to the \c \@edges section.
    12951295    GraphWriter& edges(const std::string& caption) {
    12961296      _edges_caption = caption;
    12971297      return *this;
     
    16081608    return tmp;
    16091609  }
    16101610
     1611  template <typename BGR>
     1612  class BpGraphWriter;
     1613
     1614  template <typename TBGR>
     1615  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
     1616                                    std::ostream& os = std::cout);
     1617  template <typename TBGR>
     1618  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn);
     1619  template <typename TBGR>
     1620  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn);
     1621
     1622  /// \ingroup lemon_io
     1623  ///
     1624  /// \brief \ref lgf-format "LGF" writer for undirected bipartite graphs
     1625  ///
     1626  /// This utility writes an \ref lgf-format "LGF" file.
     1627  ///
     1628  /// It can be used almost the same way as \c GraphWriter, but it
     1629  /// reads the red and blue nodes from separate sections, and these
     1630  /// sections can contain different set of maps.
     1631  ///
     1632  /// The red and blue maps are written to the corresponding
     1633  /// sections. The node maps are written to both of these sections
     1634  /// with the same map name.
     1635  template <typename BGR>
     1636  class BpGraphWriter {
     1637  public:
     1638
     1639    typedef BGR BpGraph;
     1640    TEMPLATE_BPGRAPH_TYPEDEFS(BGR);
     1641
     1642  private:
     1643
     1644
     1645    std::ostream* _os;
     1646    bool local_os;
     1647
     1648    const BGR& _graph;
     1649
     1650    std::string _nodes_caption;
     1651    std::string _edges_caption;
     1652    std::string _attributes_caption;
     1653
     1654    typedef std::map<Node, std::string> NodeIndex;
     1655    NodeIndex _node_index;
     1656    typedef std::map<Edge, std::string> EdgeIndex;
     1657    EdgeIndex _edge_index;
     1658
     1659    typedef std::vector<std::pair<std::string,
     1660      _writer_bits::MapStorageBase<Node>* > > NodeMaps;
     1661    NodeMaps _red_maps;
     1662    NodeMaps _blue_maps;
     1663
     1664    typedef std::vector<std::pair<std::string,
     1665      _writer_bits::MapStorageBase<Edge>* > >EdgeMaps;
     1666    EdgeMaps _edge_maps;
     1667
     1668    typedef std::vector<std::pair<std::string,
     1669      _writer_bits::ValueStorageBase*> > Attributes;
     1670    Attributes _attributes;
     1671
     1672    bool _skip_nodes;
     1673    bool _skip_edges;
     1674
     1675  public:
     1676
     1677    /// \brief Constructor
     1678    ///
     1679    /// Construct a bipartite graph writer, which writes to the given
     1680    /// output stream.
     1681    BpGraphWriter(const BGR& graph, std::ostream& os = std::cout)
     1682      : _os(&os), local_os(false), _graph(graph),
     1683        _skip_nodes(false), _skip_edges(false) {}
     1684
     1685    /// \brief Constructor
     1686    ///
     1687    /// Construct a bipartite graph writer, which writes to the given
     1688    /// output file.
     1689    BpGraphWriter(const BGR& graph, const std::string& fn)
     1690      : _os(new std::ofstream(fn.c_str())), local_os(true), _graph(graph),
     1691        _skip_nodes(false), _skip_edges(false) {
     1692      if (!(*_os)) {
     1693        delete _os;
     1694        throw IoError("Cannot write file", fn);
     1695      }
     1696    }
     1697
     1698    /// \brief Constructor
     1699    ///
     1700    /// Construct a bipartite graph writer, which writes to the given
     1701    /// output file.
     1702    BpGraphWriter(const BGR& graph, const char* fn)
     1703      : _os(new std::ofstream(fn)), local_os(true), _graph(graph),
     1704        _skip_nodes(false), _skip_edges(false) {
     1705      if (!(*_os)) {
     1706        delete _os;
     1707        throw IoError("Cannot write file", fn);
     1708      }
     1709    }
     1710
     1711    /// \brief Destructor
     1712    ~BpGraphWriter() {
     1713      for (typename NodeMaps::iterator it = _red_maps.begin();
     1714           it != _red_maps.end(); ++it) {
     1715        delete it->second;
     1716      }
     1717
     1718      for (typename NodeMaps::iterator it = _blue_maps.begin();
     1719           it != _blue_maps.end(); ++it) {
     1720        delete it->second;
     1721      }
     1722
     1723      for (typename EdgeMaps::iterator it = _edge_maps.begin();
     1724           it != _edge_maps.end(); ++it) {
     1725        delete it->second;
     1726      }
     1727
     1728      for (typename Attributes::iterator it = _attributes.begin();
     1729           it != _attributes.end(); ++it) {
     1730        delete it->second;
     1731      }
     1732
     1733      if (local_os) {
     1734        delete _os;
     1735      }
     1736    }
     1737
     1738  private:
     1739
     1740    template <typename TBGR>
     1741    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
     1742                                             std::ostream& os);
     1743    template <typename TBGR>
     1744    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph,
     1745                                             const std::string& fn);
     1746    template <typename TBGR>
     1747    friend BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char *fn);
     1748
     1749    BpGraphWriter(BpGraphWriter& other)
     1750      : _os(other._os), local_os(other.local_os), _graph(other._graph),
     1751        _skip_nodes(other._skip_nodes), _skip_edges(other._skip_edges) {
     1752
     1753      other._os = 0;
     1754      other.local_os = false;
     1755
     1756      _node_index.swap(other._node_index);
     1757      _edge_index.swap(other._edge_index);
     1758
     1759      _red_maps.swap(other._red_maps);
     1760      _blue_maps.swap(other._blue_maps);
     1761      _edge_maps.swap(other._edge_maps);
     1762      _attributes.swap(other._attributes);
     1763
     1764      _nodes_caption = other._nodes_caption;
     1765      _edges_caption = other._edges_caption;
     1766      _attributes_caption = other._attributes_caption;
     1767    }
     1768
     1769    BpGraphWriter& operator=(const BpGraphWriter&);
     1770
     1771  public:
     1772
     1773    /// \name Writing Rules
     1774    /// @{
     1775
     1776    /// \brief Node map writing rule
     1777    ///
     1778    /// Add a node map writing rule to the writer.
     1779    template <typename Map>
     1780    BpGraphWriter& nodeMap(const std::string& caption, const Map& map) {
     1781      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1782      _writer_bits::MapStorageBase<Node>* red_storage =
     1783        new _writer_bits::MapStorage<Node, Map>(map);
     1784      _red_maps.push_back(std::make_pair(caption, red_storage));
     1785      _writer_bits::MapStorageBase<Node>* blue_storage =
     1786        new _writer_bits::MapStorage<Node, Map>(map);
     1787      _blue_maps.push_back(std::make_pair(caption, blue_storage));
     1788      return *this;
     1789    }
     1790
     1791    /// \brief Node map writing rule
     1792    ///
     1793    /// Add a node map writing rule with specialized converter to the
     1794    /// writer.
     1795    template <typename Map, typename Converter>
     1796    BpGraphWriter& nodeMap(const std::string& caption, const Map& map,
     1797                           const Converter& converter = Converter()) {
     1798      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1799      _writer_bits::MapStorageBase<Node>* red_storage =
     1800        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
     1801      _red_maps.push_back(std::make_pair(caption, red_storage));
     1802      _writer_bits::MapStorageBase<Node>* blue_storage =
     1803        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
     1804      _blue_maps.push_back(std::make_pair(caption, blue_storage));
     1805      return *this;
     1806    }
     1807
     1808    /// \brief Red map writing rule
     1809    ///
     1810    /// Add a red map writing rule to the writer.
     1811    template <typename Map>
     1812    BpGraphWriter& redMap(const std::string& caption, const Map& map) {
     1813      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1814      _writer_bits::MapStorageBase<Node>* storage =
     1815        new _writer_bits::MapStorage<Node, Map>(map);
     1816      _red_maps.push_back(std::make_pair(caption, storage));
     1817      return *this;
     1818    }
     1819
     1820    /// \brief Red map writing rule
     1821    ///
     1822    /// Add a red map writing rule with specialized converter to the
     1823    /// writer.
     1824    template <typename Map, typename Converter>
     1825    BpGraphWriter& redMap(const std::string& caption, const Map& map,
     1826                          const Converter& converter = Converter()) {
     1827      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1828      _writer_bits::MapStorageBase<Node>* storage =
     1829        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
     1830      _red_maps.push_back(std::make_pair(caption, storage));
     1831      return *this;
     1832    }
     1833
     1834    /// \brief Blue map writing rule
     1835    ///
     1836    /// Add a blue map writing rule to the writer.
     1837    template <typename Map>
     1838    BpGraphWriter& blueMap(const std::string& caption, const Map& map) {
     1839      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1840      _writer_bits::MapStorageBase<Node>* storage =
     1841        new _writer_bits::MapStorage<Node, Map>(map);
     1842      _blue_maps.push_back(std::make_pair(caption, storage));
     1843      return *this;
     1844    }
     1845
     1846    /// \brief Blue map writing rule
     1847    ///
     1848    /// Add a blue map writing rule with specialized converter to the
     1849    /// writer.
     1850    template <typename Map, typename Converter>
     1851    BpGraphWriter& blueMap(const std::string& caption, const Map& map,
     1852                           const Converter& converter = Converter()) {
     1853      checkConcept<concepts::ReadMap<Node, typename Map::Value>, Map>();
     1854      _writer_bits::MapStorageBase<Node>* storage =
     1855        new _writer_bits::MapStorage<Node, Map, Converter>(map, converter);
     1856      _blue_maps.push_back(std::make_pair(caption, storage));
     1857      return *this;
     1858    }
     1859
     1860    /// \brief Edge map writing rule
     1861    ///
     1862    /// Add an edge map writing rule to the writer.
     1863    template <typename Map>
     1864    BpGraphWriter& edgeMap(const std::string& caption, const Map& map) {
     1865      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
     1866      _writer_bits::MapStorageBase<Edge>* storage =
     1867        new _writer_bits::MapStorage<Edge, Map>(map);
     1868      _edge_maps.push_back(std::make_pair(caption, storage));
     1869      return *this;
     1870    }
     1871
     1872    /// \brief Edge map writing rule
     1873    ///
     1874    /// Add an edge map writing rule with specialized converter to the
     1875    /// writer.
     1876    template <typename Map, typename Converter>
     1877    BpGraphWriter& edgeMap(const std::string& caption, const Map& map,
     1878                          const Converter& converter = Converter()) {
     1879      checkConcept<concepts::ReadMap<Edge, typename Map::Value>, Map>();
     1880      _writer_bits::MapStorageBase<Edge>* storage =
     1881        new _writer_bits::MapStorage<Edge, Map, Converter>(map, converter);
     1882      _edge_maps.push_back(std::make_pair(caption, storage));
     1883      return *this;
     1884    }
     1885
     1886    /// \brief Arc map writing rule
     1887    ///
     1888    /// Add an arc map writing rule to the writer.
     1889    template <typename Map>
     1890    BpGraphWriter& arcMap(const std::string& caption, const Map& map) {
     1891      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
     1892      _writer_bits::MapStorageBase<Edge>* forward_storage =
     1893        new _writer_bits::GraphArcMapStorage<BGR, true, Map>(_graph, map);
     1894      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
     1895      _writer_bits::MapStorageBase<Edge>* backward_storage =
     1896        new _writer_bits::GraphArcMapStorage<BGR, false, Map>(_graph, map);
     1897      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
     1898      return *this;
     1899    }
     1900
     1901    /// \brief Arc map writing rule
     1902    ///
     1903    /// Add an arc map writing rule with specialized converter to the
     1904    /// writer.
     1905    template <typename Map, typename Converter>
     1906    BpGraphWriter& arcMap(const std::string& caption, const Map& map,
     1907                          const Converter& converter = Converter()) {
     1908      checkConcept<concepts::ReadMap<Arc, typename Map::Value>, Map>();
     1909      _writer_bits::MapStorageBase<Edge>* forward_storage =
     1910        new _writer_bits::GraphArcMapStorage<BGR, true, Map, Converter>
     1911        (_graph, map, converter);
     1912      _edge_maps.push_back(std::make_pair('+' + caption, forward_storage));
     1913      _writer_bits::MapStorageBase<Edge>* backward_storage =
     1914        new _writer_bits::GraphArcMapStorage<BGR, false, Map, Converter>
     1915        (_graph, map, converter);
     1916      _edge_maps.push_back(std::make_pair('-' + caption, backward_storage));
     1917      return *this;
     1918    }
     1919
     1920    /// \brief Attribute writing rule
     1921    ///
     1922    /// Add an attribute writing rule to the writer.
     1923    template <typename Value>
     1924    BpGraphWriter& attribute(const std::string& caption, const Value& value) {
     1925      _writer_bits::ValueStorageBase* storage =
     1926        new _writer_bits::ValueStorage<Value>(value);
     1927      _attributes.push_back(std::make_pair(caption, storage));
     1928      return *this;
     1929    }
     1930
     1931    /// \brief Attribute writing rule
     1932    ///
     1933    /// Add an attribute writing rule with specialized converter to the
     1934    /// writer.
     1935    template <typename Value, typename Converter>
     1936    BpGraphWriter& attribute(const std::string& caption, const Value& value,
     1937                             const Converter& converter = Converter()) {
     1938      _writer_bits::ValueStorageBase* storage =
     1939        new _writer_bits::ValueStorage<Value, Converter>(value, converter);
     1940      _attributes.push_back(std::make_pair(caption, storage));
     1941      return *this;
     1942    }
     1943
     1944    /// \brief Node writing rule
     1945    ///
     1946    /// Add a node writing rule to the writer.
     1947    BpGraphWriter& node(const std::string& caption, const Node& node) {
     1948      typedef _writer_bits::MapLookUpConverter<Node> Converter;
     1949      Converter converter(_node_index);
     1950      _writer_bits::ValueStorageBase* storage =
     1951        new _writer_bits::ValueStorage<Node, Converter>(node, converter);
     1952      _attributes.push_back(std::make_pair(caption, storage));
     1953      return *this;
     1954    }
     1955
     1956    /// \brief Edge writing rule
     1957    ///
     1958    /// Add an edge writing rule to writer.
     1959    BpGraphWriter& edge(const std::string& caption, const Edge& edge) {
     1960      typedef _writer_bits::MapLookUpConverter<Edge> Converter;
     1961      Converter converter(_edge_index);
     1962      _writer_bits::ValueStorageBase* storage =
     1963        new _writer_bits::ValueStorage<Edge, Converter>(edge, converter);
     1964      _attributes.push_back(std::make_pair(caption, storage));
     1965      return *this;
     1966    }
     1967
     1968    /// \brief Arc writing rule
     1969    ///
     1970    /// Add an arc writing rule to writer.
     1971    BpGraphWriter& arc(const std::string& caption, const Arc& arc) {
     1972      typedef _writer_bits::GraphArcLookUpConverter<BGR> Converter;
     1973      Converter converter(_graph, _edge_index);
     1974      _writer_bits::ValueStorageBase* storage =
     1975        new _writer_bits::ValueStorage<Arc, Converter>(arc, converter);
     1976      _attributes.push_back(std::make_pair(caption, storage));
     1977      return *this;
     1978    }
     1979
     1980    /// \name Section Captions
     1981    /// @{
     1982
     1983    /// \brief Add an additional caption to the \c \@red_nodes and
     1984    /// \c \@blue_nodes section
     1985    ///
     1986    /// Add an additional caption to the \c \@red_nodes and \c
     1987    /// \@blue_nodes section.
     1988    BpGraphWriter& nodes(const std::string& caption) {
     1989      _nodes_caption = caption;
     1990      return *this;
     1991    }
     1992
     1993    /// \brief Add an additional caption to the \c \@edges section
     1994    ///
     1995    /// Add an additional caption to the \c \@edges section.
     1996    BpGraphWriter& edges(const std::string& caption) {
     1997      _edges_caption = caption;
     1998      return *this;
     1999    }
     2000
     2001    /// \brief Add an additional caption to the \c \@attributes section
     2002    ///
     2003    /// Add an additional caption to the \c \@attributes section.
     2004    BpGraphWriter& attributes(const std::string& caption) {
     2005      _attributes_caption = caption;
     2006      return *this;
     2007    }
     2008
     2009    /// \name Skipping Section
     2010    /// @{
     2011
     2012    /// \brief Skip writing the node set
     2013    ///
     2014    /// The \c \@red_nodes and \c \@blue_nodes section will not be
     2015    /// written to the stream.
     2016    BpGraphWriter& skipNodes() {
     2017      LEMON_ASSERT(!_skip_nodes, "Multiple usage of skipNodes() member");
     2018      _skip_nodes = true;
     2019      return *this;
     2020    }
     2021
     2022    /// \brief Skip writing edge set
     2023    ///
     2024    /// The \c \@edges section will not be written to the stream.
     2025    BpGraphWriter& skipEdges() {
     2026      LEMON_ASSERT(!_skip_edges, "Multiple usage of skipEdges() member");
     2027      _skip_edges = true;
     2028      return *this;
     2029    }
     2030
     2031    /// @}
     2032
     2033  private:
     2034
     2035    void writeRedNodes() {
     2036      _writer_bits::MapStorageBase<Node>* label = 0;
     2037      for (typename NodeMaps::iterator it = _red_maps.begin();
     2038           it != _red_maps.end(); ++it) {
     2039        if (it->first == "label") {
     2040          label = it->second;
     2041          break;
     2042        }
     2043      }
     2044
     2045      *_os << "@red_nodes";
     2046      if (!_nodes_caption.empty()) {
     2047        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
     2048      }
     2049      *_os << std::endl;
     2050
     2051      if (label == 0) {
     2052        *_os << "label" << '\t';
     2053      }
     2054      for (typename NodeMaps::iterator it = _red_maps.begin();
     2055           it != _red_maps.end(); ++it) {
     2056        _writer_bits::writeToken(*_os, it->first) << '\t';
     2057      }
     2058      *_os << std::endl;
     2059
     2060      std::vector<Node> nodes;
     2061      for (RedIt n(_graph); n != INVALID; ++n) {
     2062        nodes.push_back(n);
     2063      }
     2064
     2065      if (label == 0) {
     2066        IdMap<BGR, Node> id_map(_graph);
     2067        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
     2068        std::sort(nodes.begin(), nodes.end(), id_less);
     2069      } else {
     2070        label->sort(nodes);
     2071      }
     2072
     2073      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
     2074        Node n = nodes[i];
     2075        if (label == 0) {
     2076          std::ostringstream os;
     2077          os << _graph.id(n);
     2078          _writer_bits::writeToken(*_os, os.str());
     2079          *_os << '\t';
     2080          _node_index.insert(std::make_pair(n, os.str()));
     2081        }
     2082        for (typename NodeMaps::iterator it = _red_maps.begin();
     2083             it != _red_maps.end(); ++it) {
     2084          std::string value = it->second->get(n);
     2085          _writer_bits::writeToken(*_os, value);
     2086          if (it->first == "label") {
     2087            _node_index.insert(std::make_pair(n, value));
     2088          }
     2089          *_os << '\t';
     2090        }
     2091        *_os << std::endl;
     2092      }
     2093    }
     2094
     2095    void writeBlueNodes() {
     2096      _writer_bits::MapStorageBase<Node>* label = 0;
     2097      for (typename NodeMaps::iterator it = _blue_maps.begin();
     2098           it != _blue_maps.end(); ++it) {
     2099        if (it->first == "label") {
     2100          label = it->second;
     2101          break;
     2102        }
     2103      }
     2104
     2105      *_os << "@blue_nodes";
     2106      if (!_nodes_caption.empty()) {
     2107        _writer_bits::writeToken(*_os << ' ', _nodes_caption);
     2108      }
     2109      *_os << std::endl;
     2110
     2111      if (label == 0) {
     2112        *_os << "label" << '\t';
     2113      }
     2114      for (typename NodeMaps::iterator it = _blue_maps.begin();
     2115           it != _blue_maps.end(); ++it) {
     2116        _writer_bits::writeToken(*_os, it->first) << '\t';
     2117      }
     2118      *_os << std::endl;
     2119
     2120      std::vector<Node> nodes;
     2121      for (BlueIt n(_graph); n != INVALID; ++n) {
     2122        nodes.push_back(n);
     2123      }
     2124
     2125      if (label == 0) {
     2126        IdMap<BGR, Node> id_map(_graph);
     2127        _writer_bits::MapLess<IdMap<BGR, Node> > id_less(id_map);
     2128        std::sort(nodes.begin(), nodes.end(), id_less);
     2129      } else {
     2130        label->sort(nodes);
     2131      }
     2132
     2133      for (int i = 0; i < static_cast<int>(nodes.size()); ++i) {
     2134        Node n = nodes[i];
     2135        if (label == 0) {
     2136          std::ostringstream os;
     2137          os << _graph.id(n);
     2138          _writer_bits::writeToken(*_os, os.str());
     2139          *_os << '\t';
     2140          _node_index.insert(std::make_pair(n, os.str()));
     2141        }
     2142        for (typename NodeMaps::iterator it = _blue_maps.begin();
     2143             it != _blue_maps.end(); ++it) {
     2144          std::string value = it->second->get(n);
     2145          _writer_bits::writeToken(*_os, value);
     2146          if (it->first == "label") {
     2147            _node_index.insert(std::make_pair(n, value));
     2148          }
     2149          *_os << '\t';
     2150        }
     2151        *_os << std::endl;
     2152      }
     2153    }
     2154
     2155    void createRedNodeIndex() {
     2156      _writer_bits::MapStorageBase<Node>* label = 0;
     2157      for (typename NodeMaps::iterator it = _red_maps.begin();
     2158           it != _red_maps.end(); ++it) {
     2159        if (it->first == "label") {
     2160          label = it->second;
     2161          break;
     2162        }
     2163      }
     2164
     2165      if (label == 0) {
     2166        for (NodeIt n(_graph); n != INVALID; ++n) {
     2167          std::ostringstream os;
     2168          os << _graph.id(n);
     2169          _node_index.insert(std::make_pair(n, os.str()));
     2170        }
     2171      } else {
     2172        for (NodeIt n(_graph); n != INVALID; ++n) {
     2173          std::string value = label->get(n);
     2174          _node_index.insert(std::make_pair(n, value));
     2175        }
     2176      }
     2177    }
     2178
     2179    void createBlueNodeIndex() {
     2180      _writer_bits::MapStorageBase<Node>* label = 0;
     2181      for (typename NodeMaps::iterator it = _blue_maps.begin();
     2182           it != _blue_maps.end(); ++it) {
     2183        if (it->first == "label") {
     2184          label = it->second;
     2185          break;
     2186        }
     2187      }
     2188
     2189      if (label == 0) {
     2190        for (NodeIt n(_graph); n != INVALID; ++n) {
     2191          std::ostringstream os;
     2192          os << _graph.id(n);
     2193          _node_index.insert(std::make_pair(n, os.str()));
     2194        }
     2195      } else {
     2196        for (NodeIt n(_graph); n != INVALID; ++n) {
     2197          std::string value = label->get(n);
     2198          _node_index.insert(std::make_pair(n, value));
     2199        }
     2200      }
     2201    }
     2202
     2203    void writeEdges() {
     2204      _writer_bits::MapStorageBase<Edge>* label = 0;
     2205      for (typename EdgeMaps::iterator it = _edge_maps.begin();
     2206           it != _edge_maps.end(); ++it) {
     2207        if (it->first == "label") {
     2208          label = it->second;
     2209          break;
     2210        }
     2211      }
     2212
     2213      *_os << "@edges";
     2214      if (!_edges_caption.empty()) {
     2215        _writer_bits::writeToken(*_os << ' ', _edges_caption);
     2216      }
     2217      *_os << std::endl;
     2218
     2219      *_os << '\t' << '\t';
     2220      if (label == 0) {
     2221        *_os << "label" << '\t';
     2222      }
     2223      for (typename EdgeMaps::iterator it = _edge_maps.begin();
     2224           it != _edge_maps.end(); ++it) {
     2225        _writer_bits::writeToken(*_os, it->first) << '\t';
     2226      }
     2227      *_os << std::endl;
     2228
     2229      std::vector<Edge> edges;
     2230      for (EdgeIt n(_graph); n != INVALID; ++n) {
     2231        edges.push_back(n);
     2232      }
     2233
     2234      if (label == 0) {
     2235        IdMap<BGR, Edge> id_map(_graph);
     2236        _writer_bits::MapLess<IdMap<BGR, Edge> > id_less(id_map);
     2237        std::sort(edges.begin(), edges.end(), id_less);
     2238      } else {
     2239        label->sort(edges);
     2240      }
     2241
     2242      for (int i = 0; i < static_cast<int>(edges.size()); ++i) {
     2243        Edge e = edges[i];
     2244        _writer_bits::writeToken(*_os, _node_index.
     2245                                 find(_graph.redNode(e))->second);
     2246        *_os << '\t';
     2247        _writer_bits::writeToken(*_os, _node_index.
     2248                                 find(_graph.blueNode(e))->second);
     2249        *_os << '\t';
     2250        if (label == 0) {
     2251          std::ostringstream os;
     2252          os << _graph.id(e);
     2253          _writer_bits::writeToken(*_os, os.str());
     2254          *_os << '\t';
     2255          _edge_index.insert(std::make_pair(e, os.str()));
     2256        }
     2257        for (typename EdgeMaps::iterator it = _edge_maps.begin();
     2258             it != _edge_maps.end(); ++it) {
     2259          std::string value = it->second->get(e);
     2260          _writer_bits::writeToken(*_os, value);
     2261          if (it->first == "label") {
     2262            _edge_index.insert(std::make_pair(e, value));
     2263          }
     2264          *_os << '\t';
     2265        }
     2266        *_os << std::endl;
     2267      }
     2268    }
     2269
     2270    void createEdgeIndex() {
     2271      _writer_bits::MapStorageBase<Edge>* label = 0;
     2272      for (typename EdgeMaps::iterator it = _edge_maps.begin();
     2273           it != _edge_maps.end(); ++it) {
     2274        if (it->first == "label") {
     2275          label = it->second;
     2276          break;
     2277        }
     2278      }
     2279
     2280      if (label == 0) {
     2281        for (EdgeIt e(_graph); e != INVALID; ++e) {
     2282          std::ostringstream os;
     2283          os << _graph.id(e);
     2284          _edge_index.insert(std::make_pair(e, os.str()));
     2285        }
     2286      } else {
     2287        for (EdgeIt e(_graph); e != INVALID; ++e) {
     2288          std::string value = label->get(e);
     2289          _edge_index.insert(std::make_pair(e, value));
     2290        }
     2291      }
     2292    }
     2293
     2294    void writeAttributes() {
     2295      if (_attributes.empty()) return;
     2296      *_os << "@attributes";
     2297      if (!_attributes_caption.empty()) {
     2298        _writer_bits::writeToken(*_os << ' ', _attributes_caption);
     2299      }
     2300      *_os << std::endl;
     2301      for (typename Attributes::iterator it = _attributes.begin();
     2302           it != _attributes.end(); ++it) {
     2303        _writer_bits::writeToken(*_os, it->first) << ' ';
     2304        _writer_bits::writeToken(*_os, it->second->get());
     2305        *_os << std::endl;
     2306      }
     2307    }
     2308
     2309  public:
     2310
     2311    /// \name Execution of the Writer
     2312    /// @{
     2313
     2314    /// \brief Start the batch processing
     2315    ///
     2316    /// This function starts the batch processing.
     2317    void run() {
     2318      if (!_skip_nodes) {
     2319        writeRedNodes();
     2320        writeBlueNodes();
     2321      } else {
     2322        createRedNodeIndex();
     2323        createBlueNodeIndex();
     2324      }
     2325      if (!_skip_edges) {
     2326        writeEdges();
     2327      } else {
     2328        createEdgeIndex();
     2329      }
     2330      writeAttributes();
     2331    }
     2332
     2333    /// \brief Give back the stream of the writer
     2334    ///
     2335    /// Give back the stream of the writer
     2336    std::ostream& ostream() {
     2337      return *_os;
     2338    }
     2339
     2340    /// @}
     2341  };
     2342
     2343  /// \ingroup lemon_io
     2344  ///
     2345  /// \brief Return a \ref BpGraphWriter class
     2346  ///
     2347  /// This function just returns a \ref BpGraphWriter class.
     2348  ///
     2349  /// With this function a bipartite graph can be write to a file or output
     2350  /// stream in \ref lgf-format "LGF" format with several maps and
     2351  /// attributes. For example, with the following code a bipartite
     2352  /// weighted matching problem can be written to the standard output,
     2353  /// i.e. a graph with a \e weight map on the edges:
     2354  ///
     2355  ///\code
     2356  ///ListBpGraph graph;
     2357  ///ListBpGraph::EdgeMap<int> weight(graph);
     2358  ///  // Setting the weight map
     2359  ///bpGraphWriter(graph, std::cout).
     2360  ///  edgeMap("weight", weight).
     2361  ///  run();
     2362  ///\endcode
     2363  ///
     2364  /// For a complete documentation, please see the \ref BpGraphWriter
     2365  /// class documentation.
     2366  /// \warning Don't forget to put the \ref BpGraphWriter::run() "run()"
     2367  /// to the end of the parameter list.
     2368  /// \relates BpGraphWriter
     2369  /// \sa bpGraphWriter(const TBGR& graph, const std::string& fn)
     2370  /// \sa bpGraphWriter(const TBGR& graph, const char* fn)
     2371  template <typename TBGR>
     2372  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, std::ostream& os) {
     2373    BpGraphWriter<TBGR> tmp(graph, os);
     2374    return tmp;
     2375  }
     2376
     2377  /// \brief Return a \ref BpGraphWriter class
     2378  ///
     2379  /// This function just returns a \ref BpGraphWriter class.
     2380  /// \relates BpGraphWriter
     2381  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
     2382  template <typename TBGR>
     2383  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const std::string& fn) {
     2384    BpGraphWriter<TBGR> tmp(graph, fn);
     2385    return tmp;
     2386  }
     2387
     2388  /// \brief Return a \ref BpGraphWriter class
     2389  ///
     2390  /// This function just returns a \ref BpGraphWriter class.
     2391  /// \relates BpGraphWriter
     2392  /// \sa graphWriter(const TBGR& graph, std::ostream& os)
     2393  template <typename TBGR>
     2394  BpGraphWriter<TBGR> bpGraphWriter(const TBGR& graph, const char* fn) {
     2395    BpGraphWriter<TBGR> tmp(graph, fn);
     2396    return tmp;
     2397  }
     2398
    16112399  class SectionWriter;
    16122400
    16132401  SectionWriter sectionWriter(std::istream& is);