COIN-OR::LEMON - Graph Library

Ticket #302: 302-crossrefmap-fix-e8254acfab7d.patch

File 302-crossrefmap-fix-e8254acfab7d.patch, 6.9 KB (added by Peter Kovacs, 10 years ago)
  • lemon/maps.h

    # HG changeset patch
    # User Peter Kovacs <kpeter@inf.elte.hu>
    # Date 1248197430 -7200
    # Node ID e8254acfab7d9d057a8ae90c0c73d99bc6696831
    # Parent  709cfcba87778b15e1cc8a483c6754f054acd6ea
    Handle multiplicity in CrossRefMap (#302)
    
     - The inverse map is represented by std::multimap instead of std::map.
     - The value iterators work with multiplicity.
     - Add a function to count the items assigned to a value.
     - Extend tests.
    
    diff --git a/lemon/maps.h b/lemon/maps.h
    a b  
    19031903
    19041904  /// This class provides simple invertable graph maps.
    19051905  /// It wraps a standard graph map (\c NodeMap, \c ArcMap or \c EdgeMap)
    1906   /// and if a key is set to a new value then stores it in the inverse map.
     1906  /// and if a key is set to a new value, then stores it in the inverse map.
    19071907  ///
    19081908  /// The values of the map can be accessed
    19091909  /// with stl compatible forward iterator.
     
    19221922    typedef typename ItemSetTraits<GR, K>::
    19231923      template Map<V>::Type Map;
    19241924
    1925     typedef std::map<V, K> Container;
     1925    typedef std::multimap<V, K> Container;
    19261926    Container _inv_map;
    19271927
    19281928  public:
     
    19471947    /// This iterator is an stl compatible forward
    19481948    /// iterator on the values of the map. The values can
    19491949    /// be accessed in the <tt>[beginValue, endValue)</tt> range.
     1950    /// They are considered with multiplicity, so each value is
     1951    /// traversed for each item it is assigned to.
    19501952    class ValueIterator
    19511953      : public std::iterator<std::forward_iterator_tag, Value> {
    19521954      friend class CrossRefMap;
     
    19992001    /// Sets the value associated with the given key.
    20002002    void set(const Key& key, const Value& val) {
    20012003      Value oldval = Map::operator[](key);
    2002       typename Container::iterator it = _inv_map.find(oldval);
    2003       if (it != _inv_map.end() && it->second == key) {
    2004         _inv_map.erase(it);
     2004      typename Container::iterator it;
     2005      for (it = _inv_map.equal_range(oldval).first;
     2006           it != _inv_map.equal_range(oldval).second; ++it) {
     2007        if (it->second == key) {
     2008          _inv_map.erase(it);
     2009          break;
     2010        }
    20052011      }
    20062012      _inv_map.insert(std::make_pair(val, key));
    20072013      Map::set(key, val);
     
    20152021      return Map::operator[](key);
    20162022    }
    20172023
    2018     /// \brief Gives back the item by its value.
     2024    /// \brief Gives back an item by its value.
    20192025    ///
    2020     /// Gives back the item by its value.
    2021     Key operator()(const Value& key) const {
    2022       typename Container::const_iterator it = _inv_map.find(key);
     2026    /// This function gives back an item that is assigned to
     2027    /// the given value or \c INVALID if no such item exists.
     2028    /// If there are more items with the same associated value,
     2029    /// only one of them is returned.
     2030    Key operator()(const Value& val) const {
     2031      typename Container::const_iterator it = _inv_map.find(val);
    20232032      return it != _inv_map.end() ? it->second : INVALID;
    20242033    }
     2034   
     2035    /// \brief Returns the number of items with the given value.
     2036    ///
     2037    /// This function returns the number of items with the given value
     2038    /// associated with it.
     2039    int count(const Value &val) const {
     2040      return _inv_map.count(val);
     2041    }
    20252042
    20262043  protected:
    20272044
     
    20312048    /// \c AlterationNotifier.
    20322049    virtual void erase(const Key& key) {
    20332050      Value val = Map::operator[](key);
    2034       typename Container::iterator it = _inv_map.find(val);
    2035       if (it != _inv_map.end() && it->second == key) {
    2036         _inv_map.erase(it);
     2051      typename Container::iterator it;
     2052      for (it = _inv_map.equal_range(val).first;
     2053           it != _inv_map.equal_range(val).second; ++it) {
     2054        if (it->second == key) {
     2055          _inv_map.erase(it);
     2056          break;
     2057        }
    20372058      }
    20382059      Map::erase(key);
    20392060    }
     
    20452066    virtual void erase(const std::vector<Key>& keys) {
    20462067      for (int i = 0; i < int(keys.size()); ++i) {
    20472068        Value val = Map::operator[](keys[i]);
    2048         typename Container::iterator it = _inv_map.find(val);
    2049         if (it != _inv_map.end() && it->second == keys[i]) {
    2050           _inv_map.erase(it);
     2069        typename Container::iterator it;
     2070        for (it = _inv_map.equal_range(val).first;
     2071             it != _inv_map.equal_range(val).second; ++it) {
     2072          if (it->second == keys[i]) {
     2073            _inv_map.erase(it);
     2074            break;
     2075          }
    20512076        }
    20522077      }
    20532078      Map::erase(keys);
     
    20832108
    20842109      /// \brief Subscript operator.
    20852110      ///
    2086       /// Subscript operator. It gives back the item
    2087       /// that was last assigned to the given value.
     2111      /// Subscript operator. It gives back an item
     2112      /// that is assigned to the given value or \c INVALID
     2113      /// if no such item exists.
    20882114      Value operator[](const Key& key) const {
    20892115        return _inverted(key);
    20902116      }
  • test/maps_test.cc

    diff --git a/test/maps_test.cc b/test/maps_test.cc
    a b  
    439439                 CrossRefMap<Graph, Node, double> >();
    440440   
    441441    Graph gr;
    442     CrossRefMap<Graph, Node, char> map(gr);
     442    typedef CrossRefMap<Graph, Node, char> CRMap;
     443    typedef CRMap::ValueIterator ValueIt;
     444    CRMap map(gr);
    443445   
    444446    Node n0 = gr.addNode();
    445447    Node n1 = gr.addNode();
     
    455457          "Wrong CrossRefMap");
    456458    check(map[n2] == 'C' && map('C') == n2 && map.inverse()['C'] == n2,
    457459          "Wrong CrossRefMap");
    458          
     460    check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
     461          "Wrong CrossRefMap::count()");
     462   
     463    ValueIt it = map.beginValue();
     464    check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
     465          it == map.endValue(), "Wrong value iterator");
     466   
    459467    map.set(n2, 'A');
    460468
    461469    check(map[n0] == 'A' && map[n1] == 'B' && map[n2] == 'A',
     
    464472    check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
    465473    check(map('C') == INVALID && map.inverse()['C'] == INVALID,
    466474          "Wrong CrossRefMap");
     475    check(map.count('A') == 2 && map.count('B') == 1 && map.count('C') == 0,
     476          "Wrong CrossRefMap::count()");
     477
     478    it = map.beginValue();
     479    check(*it++ == 'A' && *it++ == 'A' && *it++ == 'B' &&
     480          it == map.endValue(), "Wrong value iterator");
    467481
    468482    map.set(n0, 'C');
    469483
    470484    check(map[n0] == 'C' && map[n1] == 'B' && map[n2] == 'A',
    471485          "Wrong CrossRefMap");
    472     check(map('A') == INVALID && map.inverse()['A'] == INVALID,
    473           "Wrong CrossRefMap");
     486    check(map('A') == n2 && map.inverse()['A'] == n2, "Wrong CrossRefMap");
    474487    check(map('B') == n1 && map.inverse()['B'] == n1, "Wrong CrossRefMap");
    475488    check(map('C') == n0 && map.inverse()['C'] == n0, "Wrong CrossRefMap");
     489    check(map.count('A') == 1 && map.count('B') == 1 && map.count('C') == 1,
     490          "Wrong CrossRefMap::count()");
     491
     492    it = map.beginValue();
     493    check(*it++ == 'A' && *it++ == 'B' && *it++ == 'C' &&
     494          it == map.endValue(), "Wrong value iterator");
    476495  }
    477496
    478497  return 0;