lemon/bits/array_map.h
author deba
Wed, 01 Mar 2006 10:25:30 +0000
changeset 1991 d7442141d9ef
parent 1946 17eb3eaad9f8
child 1996 5dc13b93f8b4
permissions -rw-r--r--
The graph adadptors can be alteration observed.
In most cases it uses the adapted graph alteration notifiers.
Only special case is now the UndirGraphAdaptor, where
we have to proxy the signals from the graph.

The SubBidirGraphAdaptor is removed, because it doest not
gives more feature than the EdgeSubGraphAdaptor<UndirGraphAdaptor<Graph>>.

The ResGraphAdaptor is based on this composition.
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
alpar@921
    19
#ifndef LEMON_ARRAY_MAP_H
alpar@921
    20
#define LEMON_ARRAY_MAP_H
deba@822
    21
deba@822
    22
#include <memory>
deba@1810
    23
#include <lemon/bits/map_extender.h>
deba@1813
    24
#include <lemon/bits/alteration_notifier.h>
deba@1669
    25
#include <lemon/concept_check.h>
deba@1669
    26
#include <lemon/concept/maps.h>
deba@822
    27
alpar@1946
    28
/// \ingroup graphmapfactory
deba@1669
    29
/// \file
deba@1669
    30
/// \brief Graph maps that construct and destruct
deba@1669
    31
/// their elements dynamically.
deba@822
    32
alpar@921
    33
namespace lemon {
deba@822
    34
alpar@1946
    35
  /// \ingroup graphmapfactory
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@1910
    40
  /// automatically indates 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@1414
    44
  /// The template parameter is the AlterationNotifier that the maps
deba@1414
    45
  /// will belong to and the Value.
deba@822
    46
klao@946
    47
  template <typename _Graph, 
klao@946
    48
	    typename _Item,
klao@946
    49
	    typename _Value>
deba@1039
    50
  class ArrayMap : public AlterationNotifier<_Item>::ObserverBase {
deba@897
    51
deba@1267
    52
    typedef _Item Item;
deba@822
    53
  public:
deba@822
    54
    /// The graph type of the maps. 
klao@946
    55
    typedef _Graph Graph;
deba@1719
    56
    /// The reference map tag.
deba@1719
    57
    typedef True ReferenceMapTag;
deba@1719
    58
deba@822
    59
    /// The key type of the maps.
alpar@987
    60
    typedef _Item Key;
deba@1719
    61
    /// The value type of the map.
deba@1719
    62
    typedef _Value Value;
deba@1719
    63
    /// The const reference type of the map.
deba@1719
    64
    typedef const _Value& ConstReference;
deba@1719
    65
    /// The reference type of the map.
deba@1719
    66
    typedef _Value& Reference;
deba@1719
    67
deba@1719
    68
    typedef const Value ConstValue;
deba@1719
    69
    typedef Value* Pointer;
deba@1719
    70
    typedef const Value* ConstPointer;
klao@946
    71
deba@1039
    72
    typedef AlterationNotifier<_Item> Registry;
klao@946
    73
deba@822
    74
    /// The MapBase of the Map which imlements the core regisitry function.
klao@946
    75
    typedef typename Registry::ObserverBase Parent;
deba@822
    76
		
deba@822
    77
deba@822
    78
klao@946
    79
  private:
deba@822
    80
    typedef std::allocator<Value> Allocator;
deba@822
    81
klao@946
    82
klao@946
    83
  public:
klao@946
    84
deba@1719
    85
    /// \brief Graph initialized map constructor.
deba@1703
    86
    ///
deba@1719
    87
    /// Graph initialized map constructor.
deba@980
    88
    ArrayMap(const Graph& _g) : graph(&_g) {
deba@1267
    89
      Item it;
deba@1267
    90
      attach(_g.getNotifier(Item()));
deba@822
    91
      allocate_memory();
deba@1267
    92
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
    93
	int id = graph->id(it);;
deba@822
    94
	allocator.construct(&(values[id]), Value());
deba@822
    95
      }								
deba@822
    96
    }
deba@822
    97
deba@1703
    98
    /// \brief Constructor to use default value to initialize the map. 
deba@1703
    99
    ///
deba@1703
   100
    /// It constructs a map and initialize all of the the map. 
deba@980
   101
    ArrayMap(const Graph& _g, const Value& _v) : graph(&_g) {
deba@1267
   102
      Item it;
deba@1039
   103
      attach(_g.getNotifier(_Item()));
deba@822
   104
      allocate_memory();
deba@1267
   105
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   106
	int id = graph->id(it);;
klao@946
   107
	allocator.construct(&(values[id]), _v);
deba@822
   108
      }								
deba@822
   109
    }
deba@822
   110
deba@1703
   111
    /// \brief Constructor to copy a map of the same map type.
deba@1703
   112
    ///
deba@1703
   113
    /// Constructor to copy a map of the same map type.     
alpar@1613
   114
    ArrayMap(const ArrayMap& copy) : Parent(), graph(copy.graph) {
klao@946
   115
      if (copy.attached()) {
klao@946
   116
	attach(*copy.getRegistry());
klao@946
   117
      }
deba@822
   118
      capacity = copy.capacity;
deba@822
   119
      if (capacity == 0) return;
deba@822
   120
      values = allocator.allocate(capacity);
deba@1267
   121
      Item it;
deba@1267
   122
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   123
	int id = graph->id(it);;
deba@891
   124
	allocator.construct(&(values[id]), copy.values[id]);
deba@822
   125
      }
deba@822
   126
    }
deba@822
   127
deba@1669
   128
    /// \brief The destructor of the map.
deba@1669
   129
    ///     
deba@1414
   130
    /// The destructor of the map.
klao@946
   131
    virtual ~ArrayMap() {      
klao@946
   132
      if (attached()) {
klao@946
   133
	clear();
klao@946
   134
	detach();
deba@822
   135
      }
deba@822
   136
    }
deba@1669
   137
		
deba@1669
   138
  private:
deba@1669
   139
deba@1669
   140
    ArrayMap& operator=(const ArrayMap&);
deba@1669
   141
deba@1669
   142
  protected:
deba@1669
   143
deba@1669
   144
    using Parent::attach;
deba@1669
   145
    using Parent::detach;
deba@1669
   146
    using Parent::attached;
deba@1669
   147
deba@1669
   148
    const Graph* getGraph() {
deba@1669
   149
      return graph;
deba@1669
   150
    }
deba@1669
   151
deba@1669
   152
deba@1669
   153
  public:
deba@1669
   154
deba@1703
   155
    /// \brief The subscript operator. 
deba@1703
   156
    ///
deba@1703
   157
    /// The subscript operator. The map can be subscripted by the
deba@1703
   158
    /// actual keys of the graph. 
deba@1267
   159
    Value& operator[](const Key& key) {
deba@980
   160
      int id = graph->id(key);
deba@822
   161
      return values[id];
deba@822
   162
    } 
deba@822
   163
		
deba@1703
   164
    /// \brief The const subscript operator.
deba@1703
   165
    ///
deba@1703
   166
    /// The const subscript operator. The map can be subscripted by the
deba@1703
   167
    /// actual keys of the graph. 
deba@1267
   168
    const Value& operator[](const Key& key) const {
deba@980
   169
      int id = graph->id(key);
deba@822
   170
      return values[id];
deba@822
   171
    }
deba@1703
   172
deba@1703
   173
    /// \brief Setter function of the map.
deba@1703
   174
    ///	
deba@1414
   175
    /// Setter function of the map. Equivalent with map[key] = val.
deba@1414
   176
    /// This is a compatibility feature with the not dereferable maps.
alpar@987
   177
    void set(const Key& key, const Value& val) {
klao@946
   178
      (*this)[key] = val;
deba@822
   179
    }
deba@1669
   180
deba@1669
   181
  protected:
deba@1703
   182
deba@1414
   183
    /// Add a new key to the map. It called by the map registry.
deba@1703
   184
         
deba@1703
   185
    virtual void add(const Key& key) {
deba@980
   186
      int id = graph->id(key);
deba@822
   187
      if (id >= capacity) {
deba@822
   188
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@822
   189
	while (new_capacity <= id) {
deba@822
   190
	  new_capacity <<= 1;
deba@822
   191
	}
klao@946
   192
	Value* new_values = allocator.allocate(new_capacity);
deba@1267
   193
	Item it;
deba@1267
   194
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   195
	  int jd = graph->id(it);;
deba@822
   196
	  if (id != jd) {
deba@822
   197
	    allocator.construct(&(new_values[jd]), values[jd]);
deba@822
   198
	    allocator.destroy(&(values[jd]));
deba@822
   199
	  }
deba@822
   200
	}
deba@822
   201
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@822
   202
	values = new_values;
deba@822
   203
	capacity = new_capacity;
deba@822
   204
      }
deba@822
   205
      allocator.construct(&(values[id]), Value());
deba@822
   206
    }
deba@1414
   207
deba@1703
   208
    virtual void add(const std::vector<Key>& keys) {
deba@1414
   209
      int max_id = -1;
deba@1414
   210
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   211
	int id = graph->id(keys[i]);
deba@1414
   212
	if (id > max_id) {
deba@1414
   213
	  max_id = id;
deba@1414
   214
	}
deba@1414
   215
      }
deba@1414
   216
      if (max_id >= capacity) {
deba@1414
   217
	int new_capacity = (capacity == 0 ? 1 : capacity);
deba@1414
   218
	while (new_capacity <= max_id) {
deba@1414
   219
	  new_capacity <<= 1;
deba@1414
   220
	}
deba@1414
   221
	Value* new_values = allocator.allocate(new_capacity);
deba@1414
   222
	Item it;
deba@1414
   223
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   224
	  int id = graph->id(it);
deba@1414
   225
	  bool found = false;
deba@1414
   226
	  for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   227
	    int jd = graph->id(keys[i]);
deba@1414
   228
	    if (id == jd) {
deba@1414
   229
	      found = true;
deba@1414
   230
	      break;
deba@1414
   231
	    }
deba@1414
   232
	  }
deba@1414
   233
	  if (found) continue;
deba@1414
   234
	  allocator.construct(&(new_values[id]), values[id]);
deba@1414
   235
	  allocator.destroy(&(values[id]));
deba@1414
   236
	}
deba@1414
   237
	if (capacity != 0) allocator.deallocate(values, capacity);
deba@1414
   238
	values = new_values;
deba@1414
   239
	capacity = new_capacity;
deba@1414
   240
      }
deba@1414
   241
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   242
	int id = graph->id(keys[i]);
deba@1414
   243
	allocator.construct(&(values[id]), Value());
deba@1414
   244
      }
deba@1414
   245
    }
deba@822
   246
		
deba@1414
   247
    /// Erase a key from the map. It called by the map registry.
deba@1414
   248
     
deba@1703
   249
    virtual void erase(const Key& key) {
deba@980
   250
      int id = graph->id(key);
deba@822
   251
      allocator.destroy(&(values[id]));
deba@822
   252
    }
deba@822
   253
deba@1703
   254
    virtual void erase(const std::vector<Key>& keys) {
deba@1414
   255
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@1414
   256
	int id = graph->id(keys[i]);
deba@1414
   257
	allocator.destroy(&(values[id]));
deba@1414
   258
      }
deba@1414
   259
    }
deba@1414
   260
deba@1703
   261
    virtual void build() {
klao@946
   262
      allocate_memory();
deba@1267
   263
      Item it;
deba@1267
   264
      for (graph->first(it); it != INVALID; graph->next(it)) {
deba@980
   265
	int id = graph->id(it);;
klao@946
   266
	allocator.construct(&(values[id]), Value());
klao@946
   267
      }								
klao@946
   268
    }
klao@946
   269
deba@1703
   270
    virtual void clear() {	
deba@822
   271
      if (capacity != 0) {
deba@1267
   272
	Item it;
deba@1267
   273
	for (graph->first(it); it != INVALID; graph->next(it)) {
deba@1414
   274
	  int id = graph->id(it);
klao@946
   275
	  allocator.destroy(&(values[id]));
klao@946
   276
	}								
deba@822
   277
	allocator.deallocate(values, capacity);
deba@822
   278
	capacity = 0;
deba@822
   279
      }
deba@822
   280
    }
deba@822
   281
deba@822
   282
  private:
deba@822
   283
      
deba@822
   284
    void allocate_memory() {
deba@980
   285
      int max_id = graph->maxId(_Item());
deba@822
   286
      if (max_id == -1) {
deba@822
   287
	capacity = 0;
deba@822
   288
	values = 0;
deba@822
   289
	return;
deba@822
   290
      }
deba@822
   291
      capacity = 1;
deba@822
   292
      while (capacity <= max_id) {
deba@822
   293
	capacity <<= 1;
deba@822
   294
      }
deba@822
   295
      values = allocator.allocate(capacity);	
deba@822
   296
    }      
deba@822
   297
klao@946
   298
    const Graph* graph;
deba@822
   299
    int capacity;
deba@822
   300
    Value* values;
deba@822
   301
    Allocator allocator;
deba@844
   302
deba@822
   303
  };		
deba@822
   304
deba@822
   305
}
deba@822
   306
alpar@921
   307
#endif //LEMON_ARRAY_MAP_H