lemon/bits/array_map.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
parent 2046 66d160810c0a
child 2260 4274224f8a7d
permissions -rw-r--r--
Update the Path concept
Concept check for paths

DirPath renamed to Path
The interface updated to the new lemon interface
Make difference between the empty path and the path from one node
Builder interface have not been changed
// I wanted but there was not accordance about it

UPath is removed
It was a buggy implementation, it could not iterate on the
nodes in the right order
Right way to use undirected paths => path of edges in undirected graphs

The tests have been modified to the current implementation
alpar@906
     1
/* -*- C++ -*-
alpar@906
     2
 *
alpar@1956
     3
 * This file is a part of LEMON, a generic C++ optimization library
alpar@1956
     4
 *
alpar@1956
     5
 * Copyright (C) 2003-2006
alpar@1956
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
alpar@1956
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
alpar@906
     8
 *
alpar@906
     9
 * Permission to use, modify and distribute this software is granted
alpar@906
    10
 * provided that this copyright notice appears in all copies. For
alpar@906
    11
 * precise terms see the accompanying LICENSE file.
alpar@906
    12
 *
alpar@906
    13
 * This software is provided "AS IS" with no warranty of any kind,
alpar@906
    14
 * express or implied, and with no claim as to its suitability for any
alpar@906
    15
 * purpose.
alpar@906
    16
 *
alpar@906
    17
 */
alpar@906
    18
deba@1996
    19
#ifndef LEMON_BITS_ARRAY_MAP_H
deba@1996
    20
#define LEMON_BITS_ARRAY_MAP_H
deba@822
    21
deba@822
    22
#include <memory>
deba@1999
    23
deba@1999
    24
#include <lemon/bits/traits.h>
deba@1813
    25
#include <lemon/bits/alteration_notifier.h>
deba@2031
    26
#include <lemon/concept_check.h>
deba@2031
    27
#include <lemon/concept/maps.h>
deba@822
    28
deba@1996
    29
/// \ingroup graphbits
deba@1669
    30
/// \file
deba@1999
    31
/// \brief Graph map based on the array storage.
deba@822
    32
alpar@921
    33
namespace lemon {
deba@822
    34
deba@1996
    35
  /// \ingroup graphbits
deba@1669
    36
  ///
deba@1669
    37
  /// \brief Graph map based on the array storage.
deba@1669
    38
  ///
deba@1414
    39
  /// The ArrayMap template class is graph map structure what
deba@1999
    40
  /// automatically updates the map when a key is added to or erased from
deba@1669
    41
  /// the map. This map uses the allocators to implement 
deba@1414
    42
  /// the container functionality.
deba@1414
    43
  ///
deba@2202
    44
  /// The template parameters are the Graph the current Item type and
deba@1999
    45
  /// the Value type of the map.
deba@1999
    46
  template <typename _Graph, typename _Item, typename _Value>
deba@1999
    47
  class ArrayMap 
deba@1999
    48
    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
deba@822
    49
  public:
deba@822
    50
    /// The graph type of the maps. 
klao@946
    51
    typedef _Graph Graph;
deba@1999
    52
    /// The item type of the map.
deba@1999
    53
    typedef _Item Item;
deba@1719
    54
    /// The reference map tag.
deba@1719
    55
    typedef True ReferenceMapTag;
deba@1719
    56
deba@822
    57
    /// The key type of the maps.
alpar@987
    58
    typedef _Item Key;
deba@1719
    59
    /// The value type of the map.
deba@1719
    60
    typedef _Value Value;
deba@1999
    61
deba@1719
    62
    /// The const reference type of the map.
deba@1719
    63
    typedef const _Value& ConstReference;
deba@1719
    64
    /// The reference type of the map.
deba@1719
    65
    typedef _Value& Reference;
deba@1719
    66
deba@1999
    67
    /// The notifier type.
deba@1999
    68
    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
klao@946
    69
deba@822
    70
    /// The MapBase of the Map which imlements the core regisitry function.
deba@1999
    71
    typedef typename Notifier::ObserverBase Parent;
deba@822
    72
		
klao@946
    73
  private:
deba@822
    74
    typedef std::allocator<Value> Allocator;
deba@822
    75
klao@946
    76
  public:
klao@946
    77
deba@1719
    78
    /// \brief Graph initialized map constructor.
deba@1703
    79
    ///
deba@1719
    80
    /// Graph initialized map constructor.
klao@2046
    81
    explicit ArrayMap(const Graph& graph) {
deba@1999
    82
      Parent::attach(graph.getNotifier(Item()));
deba@1999
    83
      allocate_memory();
deba@1999
    84
      Notifier* notifier = Parent::getNotifier();
deba@1267
    85
      Item it;
deba@1999
    86
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
    87
	int id = notifier->id(it);;
deba@822
    88
	allocator.construct(&(values[id]), Value());
deba@822
    89
      }								
deba@822
    90
    }
deba@822
    91
deba@1703
    92
    /// \brief Constructor to use default value to initialize the map. 
deba@1703
    93
    ///
deba@1703
    94
    /// It constructs a map and initialize all of the the map. 
deba@1999
    95
    ArrayMap(const Graph& graph, const Value& value) {
deba@1999
    96
      Parent::attach(graph.getNotifier(Item()));
deba@1999
    97
      allocate_memory();
deba@1999
    98
      Notifier* notifier = Parent::getNotifier();
deba@1267
    99
      Item it;
deba@1999
   100
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   101
	int id = notifier->id(it);;
deba@1999
   102
	allocator.construct(&(values[id]), value);
deba@822
   103
      }								
deba@822
   104
    }
deba@822
   105
deba@1703
   106
    /// \brief Constructor to copy a map of the same map type.
deba@1703
   107
    ///
deba@1703
   108
    /// Constructor to copy a map of the same map type.     
deba@1999
   109
    ArrayMap(const ArrayMap& copy) : Parent() {
klao@946
   110
      if (copy.attached()) {
deba@1999
   111
	attach(*copy.getNotifier());
klao@946
   112
      }
deba@822
   113
      capacity = copy.capacity;
deba@822
   114
      if (capacity == 0) return;
deba@822
   115
      values = allocator.allocate(capacity);
deba@1999
   116
      Notifier* notifier = Parent::getNotifier();
deba@1267
   117
      Item it;
deba@1999
   118
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   119
	int id = notifier->id(it);;
deba@891
   120
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   121
      }
deba@822
   122
    }
deba@822
   123
deba@2031
   124
    /// \brief Assign operator.
deba@2031
   125
    ///
deba@2031
   126
    /// This operator assigns for each item in the map the
deba@2031
   127
    /// value mapped to the same item in the copied map.  
deba@2031
   128
    /// The parameter map should be indiced with the same
deba@2031
   129
    /// itemset because this assign operator does not change
deba@2031
   130
    /// the container of the map. 
deba@2031
   131
    ArrayMap& operator=(const ArrayMap& cmap) {
deba@2031
   132
      return operator=<ArrayMap>(cmap);
deba@2031
   133
    }
deba@2031
   134
deba@2031
   135
deba@2031
   136
    /// \brief Template assign operator.
deba@2031
   137
    ///
deba@2031
   138
    /// The given parameter should be conform to the ReadMap
deba@2031
   139
    /// concecpt and could be indiced by the current item set of
deba@2031
   140
    /// the NodeMap. In this case the value for each item
deba@2031
   141
    /// is assigned by the value of the given ReadMap. 
deba@2031
   142
    template <typename CMap>
deba@2031
   143
    ArrayMap& operator=(const CMap& cmap) {
deba@2031
   144
      checkConcept<concept::ReadMap<Key, _Value>, CMap>();
deba@2031
   145
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2031
   146
      Item it;
deba@2031
   147
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2031
   148
        set(it, cmap[it]);
deba@2031
   149
      }
deba@2031
   150
      return *this;
deba@2031
   151
    }
deba@2031
   152
deba@1669
   153
    /// \brief The destructor of the map.
deba@1669
   154
    ///     
deba@1414
   155
    /// The destructor of the map.
klao@946
   156
    virtual ~ArrayMap() {      
klao@946
   157
      if (attached()) {
klao@946
   158
	clear();
klao@946
   159
	detach();
deba@822
   160
      }
deba@822
   161
    }
deba@1669
   162
		
deba@1669
   163
  protected:
deba@1669
   164
deba@1669
   165
    using Parent::attach;
deba@1669
   166
    using Parent::detach;
deba@1669
   167
    using Parent::attached;
deba@1669
   168
deba@1669
   169
  public:
deba@1669
   170
deba@1703
   171
    /// \brief The subscript operator. 
deba@1703
   172
    ///
deba@1703
   173
    /// The subscript operator. The map can be subscripted by the
deba@1703
   174
    /// actual keys of the graph. 
deba@1267
   175
    Value& operator[](const Key& key) {
deba@1999
   176
      int id = Parent::getNotifier()->id(key);
deba@822
   177
      return values[id];
deba@822
   178
    } 
deba@822
   179
		
deba@1703
   180
    /// \brief The const subscript operator.
deba@1703
   181
    ///
deba@1703
   182
    /// The const subscript operator. The map can be subscripted by the
deba@1703
   183
    /// actual keys of the graph. 
deba@1267
   184
    const Value& operator[](const Key& key) const {
deba@1999
   185
      int id = Parent::getNotifier()->id(key);
deba@822
   186
      return values[id];
deba@822
   187
    }
deba@1703
   188
deba@1703
   189
    /// \brief Setter function of the map.
deba@1703
   190
    ///	
deba@1414
   191
    /// Setter function of the map. Equivalent with map[key] = val.
deba@1414
   192
    /// This is a compatibility feature with the not dereferable maps.
alpar@987
   193
    void set(const Key& key, const Value& val) {
klao@946
   194
      (*this)[key] = val;
deba@822
   195
    }
deba@1669
   196
deba@1669
   197
  protected:
deba@1703
   198
deba@1999
   199
    /// \brief Adds a new key to the map.
deba@1999
   200
    ///		
deba@1999
   201
    /// It adds a new key to the map. It called by the observer notifier
deba@1999
   202
    /// and it overrides the add() member function of the observer base.     
deba@1703
   203
    virtual void add(const Key& key) {
deba@1999
   204
      Notifier* notifier = Parent::getNotifier();
deba@1999
   205
      int id = notifier->id(key);
deba@822
   206
      if (id >= capacity) {
deba@822
   207
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   208
	while (new_capacity <= id) {
deba@822
   209
	  new_capacity <<= 1;
deba@822
   210
	}
klao@946
   211
	Value* new_values = allocator.allocate(new_capacity);
deba@1267
   212
	Item it;
deba@1999
   213
	for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   214
	  int jd = notifier->id(it);;
deba@822
   215
	  if (id != jd) {
deba@822
   216
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   217
	    allocator.destroy(&(values[jd]));
deba@822
   218
	  }
deba@822
   219
	}
deba@822
   220
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   221
	values = new_values;
deba@822
   222
	capacity = new_capacity;
deba@822
   223
      }
deba@822
   224
      allocator.construct(&(values[id]), Value());
deba@822
   225
    }
deba@1414
   226
deba@1999
   227
    /// \brief Adds more new keys to the map.
deba@1999
   228
    ///		
deba@1999
   229
    /// It adds more new keys to the map. It called by the observer notifier
deba@1999
   230
    /// and it overrides the add() member function of the observer base.     
deba@1703
   231
    virtual void add(const std::vector<Key>& keys) {
deba@1999
   232
      Notifier* notifier = Parent::getNotifier();
deba@1414
   233
      int max_id = -1;
deba@1414
   234
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1999
   235
	int id = notifier->id(keys[i]);
deba@1414
   236
	if (id > max_id) {
deba@1414
   237
	  max_id = id;
deba@1414
   238
	}
deba@1414
   239
      }
deba@1414
   240
      if (max_id >= capacity) {
deba@1414
   241
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@1414
   242
	while (new_capacity <= max_id) {
deba@1414
   243
	  new_capacity <<= 1;
deba@1414
   244
	}
deba@1414
   245
	Value* new_values = allocator.allocate(new_capacity);
deba@1414
   246
	Item it;
deba@1999
   247
	for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   248
	  int id = notifier->id(it);
deba@1414
   249
	  bool found = false;
deba@1414
   250
	  for (int i = 0; i < (int)keys.size(); ++i) {
deba@1999
   251
	    int jd = notifier->id(keys[i]);
deba@1414
   252
	    if (id == jd) {
deba@1414
   253
	      found = true;
deba@1414
   254
	      break;
deba@1414
   255
	    }
deba@1414
   256
	  }
deba@1414
   257
	  if (found) continue;
deba@1414
   258
	  allocator.construct(&(new_values[id]), values[id]);
deba@1414
   259
	  allocator.destroy(&(values[id]));
deba@1414
   260
	}
deba@1414
   261
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@1414
   262
	values = new_values;
deba@1414
   263
	capacity = new_capacity;
deba@1414
   264
      }
deba@1414
   265
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1999
   266
	int id = notifier->id(keys[i]);
deba@1414
   267
	allocator.construct(&(values[id]), Value());
deba@1414
   268
      }
deba@1414
   269
    }
deba@822
   270
		
deba@1999
   271
    /// \brief Erase a key from the map.
deba@1999
   272
    ///
deba@1999
   273
    /// Erase a key from the map. It called by the observer notifier
deba@1999
   274
    /// and it overrides the erase() member function of the observer base.     
deba@1703
   275
    virtual void erase(const Key& key) {
deba@1999
   276
      int id = Parent::getNotifier()->id(key);
deba@822
   277
      allocator.destroy(&(values[id]));
deba@822
   278
    }
deba@822
   279
deba@1999
   280
    /// \brief Erase more keys from the map.
deba@1999
   281
    ///
deba@1999
   282
    /// Erase more keys from the map. It called by the observer notifier
deba@1999
   283
    /// and it overrides the erase() member function of the observer base.     
deba@1703
   284
    virtual void erase(const std::vector<Key>& keys) {
deba@1414
   285
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1999
   286
	int id = Parent::getNotifier()->id(keys[i]);
deba@1414
   287
	allocator.destroy(&(values[id]));
deba@1414
   288
      }
deba@1414
   289
    }
deba@1414
   290
deba@1999
   291
    /// \brief Buildes the map.
deba@1999
   292
    ///	
deba@1999
   293
    /// It buildes the map. It called by the observer notifier
deba@1999
   294
    /// and it overrides the build() member function of the observer base. 
deba@1703
   295
    virtual void build() {
deba@1999
   296
      Notifier* notifier = Parent::getNotifier();
klao@946
   297
      allocate_memory();
deba@1267
   298
      Item it;
deba@1999
   299
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   300
	int id = notifier->id(it);;
klao@946
   301
	allocator.construct(&(values[id]), Value());
klao@946
   302
      }								
klao@946
   303
    }
klao@946
   304
deba@1999
   305
    /// \brief Clear the map.
deba@1999
   306
    ///
deba@1999
   307
    /// It erase all items from the map. It called by the observer notifier
deba@1999
   308
    /// and it overrides the clear() member function of the observer base.     
deba@1703
   309
    virtual void clear() {	
deba@1999
   310
      Notifier* notifier = Parent::getNotifier();
deba@822
   311
      if (capacity != 0) {
deba@1267
   312
	Item it;
deba@1999
   313
	for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@1999
   314
	  int id = notifier->id(it);
klao@946
   315
	  allocator.destroy(&(values[id]));
klao@946
   316
	}								
deba@822
   317
	allocator.deallocate(values, capacity);
deba@822
   318
	capacity = 0;
deba@822
   319
      }
deba@822
   320
    }
deba@822
   321
deba@822
   322
  private:
deba@822
   323
      
deba@822
   324
    void allocate_memory() {
deba@1999
   325
      int max_id = Parent::getNotifier()->maxId();
deba@822
   326
      if (max_id == -1) {
deba@822
   327
	capacity = 0;
deba@822
   328
	values = 0;
deba@822
   329
	return;
deba@822
   330
      }
deba@822
   331
      capacity = 1;
deba@822
   332
      while (capacity <= max_id) {
deba@822
   333
	capacity <<= 1;
deba@822
   334
      }
deba@822
   335
      values = allocator.allocate(capacity);	
deba@822
   336
    }      
deba@822
   337
deba@822
   338
    int capacity;
deba@822
   339
    Value* values;
deba@822
   340
    Allocator allocator;
deba@844
   341
deba@822
   342
  };		
deba@822
   343
deba@822
   344
}
deba@822
   345
deba@1996
   346
#endif