lemon/bits/debug_map.h
author deba
Tue, 17 Oct 2006 10:50:57 +0000
changeset 2247 269a0dcee70b
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
deba@2202
     1
/* -*- C++ -*-
deba@2202
     2
 *
deba@2202
     3
 * This file is a part of LEMON, a generic C++ optimization library
deba@2202
     4
 *
deba@2202
     5
 * Copyright (C) 2003-2006
deba@2202
     6
 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
deba@2202
     7
 * (Egervary Research Group on Combinatorial Optimization, EGRES).
deba@2202
     8
 *
deba@2202
     9
 * Permission to use, modify and distribute this software is granted
deba@2202
    10
 * provided that this copyright notice appears in all copies. For
deba@2202
    11
 * precise terms see the accompanying LICENSE file.
deba@2202
    12
 *
deba@2202
    13
 * This software is provided "AS IS" with no warranty of any kind,
deba@2202
    14
 * express or implied, and with no claim as to its suitability for any
deba@2202
    15
 * purpose.
deba@2202
    16
 *
deba@2202
    17
 */
deba@2202
    18
deba@2202
    19
#ifndef LEMON_BITS_DEBUG_MAP_H
deba@2202
    20
#define LEMON_BITS_DEBUG_MAP_H
deba@2202
    21
deba@2202
    22
#include <vector>
deba@2202
    23
#include <algorithm>
deba@2202
    24
deba@2202
    25
#include <lemon/bits/traits.h>
deba@2202
    26
#include <lemon/bits/utility.h>
deba@2202
    27
#include <lemon/error.h>
deba@2202
    28
deba@2202
    29
#include <lemon/bits/alteration_notifier.h>
deba@2202
    30
deba@2202
    31
#include <lemon/concept_check.h>
deba@2202
    32
#include <lemon/concept/maps.h>
deba@2202
    33
deba@2202
    34
///\ingroup graphbits
deba@2202
    35
///
deba@2202
    36
///\file
deba@2202
    37
///\brief Vector based graph maps for debugging.
deba@2202
    38
namespace lemon {
deba@2202
    39
deba@2202
    40
  /// \ingroup graphbits
deba@2202
    41
  ///
deba@2202
    42
  /// \brief Graph map based on the std::vector storage.
deba@2202
    43
  ///
deba@2202
    44
  /// The DebugMap template class is graph map structure what
deba@2202
    45
  /// automatically updates the map when a key is added to or erased from
deba@2202
    46
  /// the map. This map also checks some programming failures by example
deba@2202
    47
  /// multiple addition of items, erasing of not existing item or
deba@2202
    48
  /// not erased items at the destruction of the map. It helps the
deba@2202
    49
  /// programmer to avoid segmentation faults and memory leaks.
deba@2202
    50
  ///
deba@2202
    51
  /// \param Notifier The AlterationNotifier that will notify this map.
deba@2202
    52
  /// \param Item The item type of the graph items.
deba@2202
    53
  /// \param Value The value type of the map.
deba@2202
    54
  /// 
deba@2202
    55
  /// \author Balazs Dezso  	
deba@2202
    56
  template <typename _Graph, typename _Item, typename _Value>
deba@2202
    57
  class DebugMap 
deba@2202
    58
    : public ItemSetTraits<_Graph, _Item>::ItemNotifier::ObserverBase {
deba@2202
    59
  private:
deba@2202
    60
		
deba@2202
    61
    /// The container type of the map.
deba@2202
    62
    typedef std::vector<_Value> Container;	
deba@2202
    63
deba@2202
    64
    /// The container type of the debug flags.
deba@2202
    65
    typedef std::vector<bool> Flag;	
deba@2202
    66
deba@2202
    67
  public:
deba@2202
    68
deba@2202
    69
    static const bool strictCheck = true;
deba@2202
    70
deba@2202
    71
    struct MapError {
deba@2202
    72
    public:
deba@2202
    73
      virtual ~MapError() {}
deba@2202
    74
      virtual const char* what() const throw() {
deba@2202
    75
        return "lemon::DebugMap::MapError";
deba@2202
    76
      }
deba@2202
    77
    };
deba@2202
    78
deba@2202
    79
    /// The graph type of the map. 
deba@2202
    80
    typedef _Graph Graph;
deba@2202
    81
    /// The item type of the map.
deba@2202
    82
    typedef _Item Item;
deba@2202
    83
    /// The reference map tag.
deba@2202
    84
    typedef True ReferenceMapTag;
deba@2202
    85
deba@2202
    86
    /// The key type of the map.
deba@2202
    87
    typedef _Item Key;
deba@2202
    88
    /// The value type of the map.
deba@2202
    89
    typedef _Value Value;
deba@2202
    90
deba@2202
    91
    /// The notifier type.
deba@2202
    92
    typedef typename ItemSetTraits<_Graph, _Item>::ItemNotifier Notifier;
deba@2202
    93
deba@2202
    94
    /// The map type.
deba@2202
    95
    typedef DebugMap Map;
deba@2202
    96
    /// The base class of the map.
deba@2202
    97
    typedef typename Notifier::ObserverBase Parent;
deba@2202
    98
deba@2202
    99
    /// The reference type of the map;
deba@2202
   100
    typedef typename Container::reference Reference;
deba@2202
   101
    /// The const reference type of the map;
deba@2202
   102
    typedef typename Container::const_reference ConstReference;
deba@2202
   103
deba@2202
   104
deba@2202
   105
    /// \brief Constructor to attach the new map into the notifier.
deba@2202
   106
    ///
deba@2202
   107
    /// It constructs a map and attachs it into the notifier.
deba@2202
   108
    /// It adds all the items of the graph to the map.
deba@2202
   109
    DebugMap(const Graph& graph) {
deba@2202
   110
      Parent::attach(graph.getNotifier(Item()));
deba@2202
   111
      container.resize(Parent::getNotifier()->maxId() + 1);
deba@2202
   112
      flag.resize(Parent::getNotifier()->maxId() + 1, false);
deba@2202
   113
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   114
      Item it;
deba@2202
   115
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   116
        flag[Parent::getNotifier()->id(it)] = true;
deba@2202
   117
      }
deba@2202
   118
    }
deba@2202
   119
deba@2202
   120
    /// \brief Constructor uses given value to initialize the map. 
deba@2202
   121
    ///
deba@2202
   122
    /// It constructs a map uses a given value to initialize the map. 
deba@2202
   123
    /// It adds all the items of the graph to the map.
deba@2202
   124
    DebugMap(const Graph& graph, const Value& value) {
deba@2202
   125
      Parent::attach(graph.getNotifier(Item()));
deba@2202
   126
      container.resize(Parent::getNotifier()->maxId() + 1, value);
deba@2202
   127
      flag.resize(Parent::getNotifier()->maxId() + 1, false);
deba@2202
   128
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   129
      Item it;
deba@2202
   130
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   131
        flag[Parent::getNotifier()->id(it)] = true;
deba@2202
   132
      }
deba@2202
   133
    }
deba@2202
   134
deba@2202
   135
    /// \brief Copy constructor
deba@2202
   136
    ///
deba@2202
   137
    /// Copy constructor.
deba@2202
   138
    DebugMap(const DebugMap& _copy) : Parent() {
deba@2202
   139
      if (_copy.attached()) {
deba@2202
   140
	Parent::attach(*_copy.getNotifier());
deba@2202
   141
	container = _copy.container;
deba@2202
   142
      }
deba@2202
   143
      flag.resize(Parent::getNotifier()->maxId() + 1, false);
deba@2202
   144
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   145
      Item it;
deba@2202
   146
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   147
        flag[Parent::getNotifier()->id(it)] = true;
deba@2202
   148
        LEMON_ASSERT(_copy.flag[Parent::getNotifier()->id(it)], MapError());
deba@2202
   149
      }
deba@2202
   150
    }
deba@2202
   151
deba@2202
   152
    /// \brief Destructor
deba@2202
   153
    ///
deba@2202
   154
    /// Destructor.
deba@2202
   155
    ~DebugMap() {
deba@2202
   156
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   157
      if (notifier != 0) {
deba@2202
   158
        Item it;
deba@2202
   159
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   160
          LEMON_ASSERT(flag[Parent::getNotifier()->id(it)], MapError());
deba@2202
   161
          flag[Parent::getNotifier()->id(it)] = false;
deba@2202
   162
        }
deba@2202
   163
      }
deba@2202
   164
      for (int i = 0; i < (int)flag.size(); ++i) {
deba@2202
   165
        LEMON_ASSERT(!flag[i], MapError());
deba@2202
   166
      }
deba@2202
   167
    }
deba@2202
   168
deba@2202
   169
    /// \brief Assign operator.
deba@2202
   170
    ///
deba@2202
   171
    /// This operator assigns for each item in the map the
deba@2202
   172
    /// value mapped to the same item in the copied map.  
deba@2202
   173
    /// The parameter map should be indiced with the same
deba@2202
   174
    /// itemset because this assign operator does not change
deba@2202
   175
    /// the container of the map. 
deba@2202
   176
    DebugMap& operator=(const DebugMap& cmap) {
deba@2202
   177
      return operator=<DebugMap>(cmap);
deba@2202
   178
    }
deba@2202
   179
deba@2202
   180
deba@2202
   181
    /// \brief Template assign operator.
deba@2202
   182
    ///
deba@2202
   183
    /// The given parameter should be conform to the ReadMap
deba@2202
   184
    /// concecpt and could be indiced by the current item set of
deba@2202
   185
    /// the NodeMap. In this case the value for each item
deba@2202
   186
    /// is assigned by the value of the given ReadMap. 
deba@2202
   187
    template <typename CMap>
deba@2202
   188
    DebugMap& operator=(const CMap& cmap) {
deba@2202
   189
      checkConcept<concept::ReadMap<Key, _Value>, CMap>();
deba@2202
   190
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   191
      Item it;
deba@2202
   192
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   193
        set(it, cmap[it]);
deba@2202
   194
      }
deba@2202
   195
      return *this;
deba@2202
   196
    }
deba@2202
   197
    
deba@2202
   198
  public:
deba@2202
   199
deba@2202
   200
    /// \brief The subcript operator.
deba@2202
   201
    ///
deba@2202
   202
    /// The subscript operator. The map can be subscripted by the
deba@2202
   203
    /// actual items of the graph.      
deba@2202
   204
    Reference operator[](const Key& key) {
deba@2202
   205
      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
deba@2202
   206
      return container[Parent::getNotifier()->id(key)];
deba@2202
   207
    } 
deba@2202
   208
		
deba@2202
   209
    /// \brief The const subcript operator.
deba@2202
   210
    ///
deba@2202
   211
    /// The const subscript operator. The map can be subscripted by the
deba@2202
   212
    /// actual items of the graph. 
deba@2202
   213
    ConstReference operator[](const Key& key) const {
deba@2202
   214
      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
deba@2202
   215
      return container[Parent::getNotifier()->id(key)];
deba@2202
   216
    }
deba@2202
   217
deba@2202
   218
deba@2202
   219
    /// \brief The setter function of the map.
deba@2202
   220
    ///
deba@2202
   221
    /// It the same as operator[](key) = value expression.
deba@2202
   222
    void set(const Key& key, const Value& value) {
deba@2202
   223
      (*this)[key] = value;
deba@2202
   224
    }
deba@2202
   225
deba@2202
   226
  protected:
deba@2202
   227
deba@2202
   228
    /// \brief Adds a new key to the map.
deba@2202
   229
    ///		
deba@2202
   230
    /// It adds a new key to the map. It called by the observer notifier
deba@2202
   231
    /// and it overrides the add() member function of the observer base.     
deba@2202
   232
    virtual void add(const Key& key) {
deba@2202
   233
      int id = Parent::getNotifier()->id(key);
deba@2202
   234
      if (id >= (int)container.size()) {
deba@2202
   235
	container.resize(id + 1);
deba@2202
   236
        flag.resize(id + 1, false);
deba@2202
   237
      }
deba@2202
   238
      LEMON_ASSERT(!flag[Parent::getNotifier()->id(key)], MapError());
deba@2202
   239
      flag[Parent::getNotifier()->id(key)] = true;
deba@2202
   240
      if (strictCheck) {
deba@2202
   241
        std::vector<bool> fl(flag.size(), false);
deba@2202
   242
        const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   243
        Item it;
deba@2202
   244
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   245
          int id = Parent::getNotifier()->id(it);
deba@2202
   246
          fl[id] = true;
deba@2202
   247
        }
deba@2202
   248
        LEMON_ASSERT(fl == flag, MapError());
deba@2202
   249
      }
deba@2202
   250
    }
deba@2202
   251
deba@2202
   252
    /// \brief Adds more new keys to the map.
deba@2202
   253
    ///		
deba@2202
   254
    /// It adds more new keys to the map. It called by the observer notifier
deba@2202
   255
    /// and it overrides the add() member function of the observer base.     
deba@2202
   256
    virtual void add(const std::vector<Key>& keys) {
deba@2202
   257
      int max = container.size() - 1;
deba@2202
   258
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@2202
   259
        int id = Parent::getNotifier()->id(keys[i]);
deba@2202
   260
        if (id >= max) {
deba@2202
   261
          max = id;
deba@2202
   262
        }
deba@2202
   263
      }
deba@2202
   264
      container.resize(max + 1);
deba@2202
   265
      flag.resize(max + 1, false);
deba@2202
   266
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@2202
   267
        LEMON_ASSERT(!flag[Parent::getNotifier()->id(keys[i])], MapError());
deba@2202
   268
        flag[Parent::getNotifier()->id(keys[i])] = true;
deba@2202
   269
      }
deba@2202
   270
      if (strictCheck) {
deba@2202
   271
        std::vector<bool> fl(flag.size(), false);
deba@2202
   272
        const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   273
        Item it;
deba@2202
   274
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   275
          int id = Parent::getNotifier()->id(it);
deba@2202
   276
          fl[id] = true;
deba@2202
   277
        }
deba@2202
   278
        LEMON_ASSERT(fl == flag, MapError());
deba@2202
   279
      }
deba@2202
   280
    }
deba@2202
   281
deba@2202
   282
    /// \brief Erase a key from the map.
deba@2202
   283
    ///
deba@2202
   284
    /// Erase a key from the map. It called by the observer notifier
deba@2202
   285
    /// and it overrides the erase() member function of the observer base.     
deba@2202
   286
    virtual void erase(const Key& key) {
deba@2202
   287
      if (strictCheck) {
deba@2202
   288
        std::vector<bool> fl(flag.size(), false);
deba@2202
   289
        const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   290
        Item it;
deba@2202
   291
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   292
          int id = Parent::getNotifier()->id(it);
deba@2202
   293
          fl[id] = true;
deba@2202
   294
        }
deba@2202
   295
        LEMON_ASSERT(fl == flag, MapError());
deba@2202
   296
      }
deba@2202
   297
      container[Parent::getNotifier()->id(key)] = Value();
deba@2202
   298
      LEMON_ASSERT(flag[Parent::getNotifier()->id(key)], MapError());
deba@2202
   299
      flag[Parent::getNotifier()->id(key)] = false;
deba@2202
   300
    }
deba@2202
   301
deba@2202
   302
    /// \brief Erase more keys from the map.
deba@2202
   303
    ///
deba@2202
   304
    /// Erase more keys from the map. It called by the observer notifier
deba@2202
   305
    /// and it overrides the erase() member function of the observer base.     
deba@2202
   306
    virtual void erase(const std::vector<Key>& keys) {
deba@2202
   307
      if (strictCheck) {
deba@2202
   308
        std::vector<bool> fl(flag.size(), false);
deba@2202
   309
        const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   310
        Item it;
deba@2202
   311
        for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   312
          int id = Parent::getNotifier()->id(it);
deba@2202
   313
          fl[id] = true;
deba@2202
   314
        }
deba@2202
   315
        LEMON_ASSERT(fl == flag, MapError());
deba@2202
   316
      }
deba@2202
   317
      for (int i = 0; i < (int)keys.size(); ++i) {
deba@2202
   318
	container[Parent::getNotifier()->id(keys[i])] = Value();
deba@2202
   319
        LEMON_ASSERT(flag[Parent::getNotifier()->id(keys[i])], MapError());
deba@2202
   320
        flag[Parent::getNotifier()->id(keys[i])] = false;
deba@2202
   321
      }
deba@2202
   322
    }
deba@2202
   323
    
deba@2202
   324
    /// \brief Buildes the map.
deba@2202
   325
    ///	
deba@2202
   326
    /// It buildes the map. It called by the observer notifier
deba@2202
   327
    /// and it overrides the build() member function of the observer base.
deba@2202
   328
    virtual void build() { 
deba@2202
   329
      if (strictCheck) {
deba@2202
   330
        for (int i = 0; i < (int)flag.size(); ++i) {
deba@2202
   331
          LEMON_ASSERT(flag[i], MapError());
deba@2202
   332
        }
deba@2202
   333
      }
deba@2202
   334
      int size = Parent::getNotifier()->maxId() + 1;
deba@2202
   335
      container.reserve(size);
deba@2202
   336
      container.resize(size);
deba@2202
   337
      flag.reserve(size);
deba@2202
   338
      flag.resize(size, false);
deba@2202
   339
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   340
      Item it;
deba@2202
   341
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   342
        int id = Parent::getNotifier()->id(it);
deba@2202
   343
        LEMON_ASSERT(!flag[id], MapError());
deba@2202
   344
        flag[id] = true;
deba@2202
   345
      }
deba@2202
   346
    }
deba@2202
   347
deba@2202
   348
    /// \brief Clear the map.
deba@2202
   349
    ///
deba@2202
   350
    /// It erase all items from the map. It called by the observer notifier
deba@2202
   351
    /// and it overrides the clear() member function of the observer base.     
deba@2202
   352
    virtual void clear() { 
deba@2202
   353
      const typename Parent::Notifier* notifier = Parent::getNotifier();
deba@2202
   354
      Item it;
deba@2202
   355
      for (notifier->first(it); it != INVALID; notifier->next(it)) {
deba@2202
   356
        int id = Parent::getNotifier()->id(it);
deba@2202
   357
        LEMON_ASSERT(flag[id], MapError());
deba@2202
   358
        flag[id] = false;
deba@2202
   359
      }
deba@2202
   360
      if (strictCheck) {
deba@2202
   361
        for (int i = 0; i < (int)flag.size(); ++i) {
deba@2202
   362
          LEMON_ASSERT(!flag[i], MapError());
deba@2202
   363
        }
deba@2202
   364
      }
deba@2202
   365
      container.clear();
deba@2202
   366
      flag.clear();
deba@2202
   367
    }
deba@2202
   368
    
deba@2202
   369
  private:
deba@2202
   370
		
deba@2202
   371
    Container container;
deba@2202
   372
    Flag flag;
deba@2202
   373
deba@2202
   374
  };
deba@2202
   375
deba@2202
   376
}
deba@2202
   377
deba@2202
   378
#endif