1 /* -*- mode: C++; indent-tabs-mode: nil; -*-
3 * This file is a part of LEMON, a generic C++ optimization library.
5 * Copyright (C) 2003-2009
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
19 #ifndef LEMON_BITS_ARRAY_MAP_H
20 #define LEMON_BITS_ARRAY_MAP_H
24 #include <lemon/bits/traits.h>
25 #include <lemon/bits/alteration_notifier.h>
26 #include <lemon/concept_check.h>
27 #include <lemon/concepts/maps.h>
31 // \brief Graph map based on the array storage.
37 // \brief Graph map based on the array storage.
39 // The ArrayMap template class is graph map structure that automatically
40 // updates the map when a key is added to or erased from the graph.
41 // This map uses the allocators to implement the container functionality.
43 // The template parameters are the Graph, the current Item type and
44 // the Value type of the map.
45 template <typename _Graph, typename _Item, typename _Value>
47 : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
50 typedef _Graph GraphType;
53 // The reference map tag.
54 typedef True ReferenceMapTag;
56 // The key type of the map.
58 // The value type of the map.
61 // The const reference type of the map.
62 typedef const _Value& ConstReference;
63 // The reference type of the map.
64 typedef _Value& Reference;
70 typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
74 // The MapBase of the Map which imlements the core regisitry function.
75 typedef typename Notifier::ObserverBase Parent;
77 typedef std::allocator<Value> Allocator;
81 // \brief Graph initialized map constructor.
83 // Graph initialized map constructor.
84 explicit ArrayMap(const GraphType& graph) {
85 Parent::attach(graph.notifier(Item()));
87 Notifier* nf = Parent::notifier();
89 for (nf->first(it); it != INVALID; nf->next(it)) {
91 allocator.construct(&(values[id]), Value());
95 // \brief Constructor to use default value to initialize the map.
97 // It constructs a map and initialize all of the the map.
98 ArrayMap(const GraphType& graph, const Value& value) {
99 Parent::attach(graph.notifier(Item()));
101 Notifier* nf = Parent::notifier();
103 for (nf->first(it); it != INVALID; nf->next(it)) {
104 int id = nf->id(it);;
105 allocator.construct(&(values[id]), value);
110 // \brief Constructor to copy a map of the same map type.
112 // Constructor to copy a map of the same map type.
113 ArrayMap(const ArrayMap& copy) : Parent() {
114 if (copy.attached()) {
115 attach(*copy.notifier());
117 capacity = copy.capacity;
118 if (capacity == 0) return;
119 values = allocator.allocate(capacity);
120 Notifier* nf = Parent::notifier();
122 for (nf->first(it); it != INVALID; nf->next(it)) {
123 int id = nf->id(it);;
124 allocator.construct(&(values[id]), copy.values[id]);
128 // \brief Assign operator.
130 // This operator assigns for each item in the map the
131 // value mapped to the same item in the copied map.
132 // The parameter map should be indiced with the same
133 // itemset because this assign operator does not change
134 // the container of the map.
135 ArrayMap& operator=(const ArrayMap& cmap) {
136 return operator=<ArrayMap>(cmap);
140 // \brief Template assign operator.
142 // The given parameter should conform to the ReadMap
143 // concecpt and could be indiced by the current item set of
144 // the NodeMap. In this case the value for each item
145 // is assigned by the value of the given ReadMap.
146 template <typename CMap>
147 ArrayMap& operator=(const CMap& cmap) {
148 checkConcept<concepts::ReadMap<Key, _Value>, CMap>();
149 const typename Parent::Notifier* nf = Parent::notifier();
151 for (nf->first(it); it != INVALID; nf->next(it)) {
158 // \brief The destructor of the map.
160 // The destructor of the map.
161 virtual ~ArrayMap() {
170 using Parent::attach;
171 using Parent::detach;
172 using Parent::attached;
176 // \brief The subscript operator.
178 // The subscript operator. The map can be subscripted by the
179 // actual keys of the graph.
180 Value& operator[](const Key& key) {
181 int id = Parent::notifier()->id(key);
185 // \brief The const subscript operator.
187 // The const subscript operator. The map can be subscripted by the
188 // actual keys of the graph.
189 const Value& operator[](const Key& key) const {
190 int id = Parent::notifier()->id(key);
194 // \brief Setter function of the map.
196 // Setter function of the map. Equivalent with map[key] = val.
197 // This is a compatibility feature with the not dereferable maps.
198 void set(const Key& key, const Value& val) {
204 // \brief Adds a new key to the map.
206 // It adds a new key to the map. It is called by the observer notifier
207 // and it overrides the add() member function of the observer base.
208 virtual void add(const Key& key) {
209 Notifier* nf = Parent::notifier();
210 int id = nf->id(key);
211 if (id >= capacity) {
212 int new_capacity = (capacity == 0 ? 1 : capacity);
213 while (new_capacity <= id) {
216 Value* new_values = allocator.allocate(new_capacity);
218 for (nf->first(it); it != INVALID; nf->next(it)) {
219 int jd = nf->id(it);;
221 allocator.construct(&(new_values[jd]), values[jd]);
222 allocator.destroy(&(values[jd]));
225 if (capacity != 0) allocator.deallocate(values, capacity);
227 capacity = new_capacity;
229 allocator.construct(&(values[id]), Value());
232 // \brief Adds more new keys to the map.
234 // It adds more new keys to the map. It is called by the observer notifier
235 // and it overrides the add() member function of the observer base.
236 virtual void add(const std::vector<Key>& keys) {
237 Notifier* nf = Parent::notifier();
239 for (int i = 0; i < int(keys.size()); ++i) {
240 int id = nf->id(keys[i]);
245 if (max_id >= capacity) {
246 int new_capacity = (capacity == 0 ? 1 : capacity);
247 while (new_capacity <= max_id) {
250 Value* new_values = allocator.allocate(new_capacity);
252 for (nf->first(it); it != INVALID; nf->next(it)) {
255 for (int i = 0; i < int(keys.size()); ++i) {
256 int jd = nf->id(keys[i]);
263 allocator.construct(&(new_values[id]), values[id]);
264 allocator.destroy(&(values[id]));
266 if (capacity != 0) allocator.deallocate(values, capacity);
268 capacity = new_capacity;
270 for (int i = 0; i < int(keys.size()); ++i) {
271 int id = nf->id(keys[i]);
272 allocator.construct(&(values[id]), Value());
276 // \brief Erase a key from the map.
278 // Erase a key from the map. It is called by the observer notifier
279 // and it overrides the erase() member function of the observer base.
280 virtual void erase(const Key& key) {
281 int id = Parent::notifier()->id(key);
282 allocator.destroy(&(values[id]));
285 // \brief Erase more keys from the map.
287 // Erase more keys from the map. It is called by the observer notifier
288 // and it overrides the erase() member function of the observer base.
289 virtual void erase(const std::vector<Key>& keys) {
290 for (int i = 0; i < int(keys.size()); ++i) {
291 int id = Parent::notifier()->id(keys[i]);
292 allocator.destroy(&(values[id]));
296 // \brief Builds the map.
298 // It builds the map. It is called by the observer notifier
299 // and it overrides the build() member function of the observer base.
300 virtual void build() {
301 Notifier* nf = Parent::notifier();
304 for (nf->first(it); it != INVALID; nf->next(it)) {
305 int id = nf->id(it);;
306 allocator.construct(&(values[id]), Value());
310 // \brief Clear the map.
312 // It erase all items from the map. It is called by the observer notifier
313 // and it overrides the clear() member function of the observer base.
314 virtual void clear() {
315 Notifier* nf = Parent::notifier();
318 for (nf->first(it); it != INVALID; nf->next(it)) {
320 allocator.destroy(&(values[id]));
322 allocator.deallocate(values, capacity);
329 void allocate_memory() {
330 int max_id = Parent::notifier()->maxId();
337 while (capacity <= max_id) {
340 values = allocator.allocate(capacity);