All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
bimap.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 // 2013 Piotr Smulewicz
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See
6 // accompanying file LICENSE_1_0.txt or copy at
7 // http://www.boost.org/LICENSE_1_0.txt)
8 //=======================================================================
16 #ifndef PAAL_BIMAP_HPP
17 #define PAAL_BIMAP_HPP
18 
20 #include "paal/utils/irange.hpp"
21 
22 #include <boost/multi_index_container.hpp>
23 #include <boost/multi_index/random_access_index.hpp>
24 #include <boost/multi_index/hashed_index.hpp>
25 #include <boost/functional/hash.hpp>
26 
27 #include <unordered_map>
28 
29 namespace paal {
30 namespace data_structures {
31 
40 template <typename T, typename Idx = int> class bimap_mic {
41  public:
42 
43  bimap_mic() = default;
44 
51  template <typename Range> bimap_mic(Range && range) {
52  std::size_t s = boost::distance(range);
53  m_index.reserve(s);
54  for (const T &t : range) {
55  add(t);
56  }
57  }
58 
66  Idx get_idx(const T &t) const {
67  auto const &idx = m_index.template get<1>();
68  return m_index.template project<0>(idx.find(t)) - m_index.begin();
69  }
70 
78  const T &get_val(Idx i) const {
79 #ifdef NDEBUG
80  return m_index[i];
81 #else
82  return m_index.at(i);
83 #endif
84  }
85 
91  std::size_t size() const { return m_index.size(); }
92 
100  Idx add(const T &t) {
101  m_index.push_back(t);
102  return m_index.size() - 1;
103  }
104 
105  private:
106  typedef boost::multi_index_container<
107  T, boost::multi_index::indexed_by<boost::multi_index::random_access<>,
108  boost::multi_index::hashed_unique<
109  boost::multi_index::identity<T>>>>
110  bm_type;
111  bm_type m_index;
112 };
113 
114 // minor TODO write specification when T is integral (copy instead of reference)
123 template <typename T, typename Idx = int> class bimap {
124  typedef std::unordered_map<T, Idx, boost::hash<T>> TToID;
125 
126  public:
127  typedef typename TToID::const_iterator Iterator;
128 
129  bimap() = default;
130 
137  template <typename Range> bimap(Range && range) {
138  std::size_t s = boost::distance(range);
139  m_id_to_t.reserve(s);
140  m_t_to_id.reserve(s);
141  for (const T &t : range) {
142  add(t);
143  }
144  }
145 
153  Idx get_idx(const T &t) const {
154  auto iter = m_t_to_id.find(t);
155  assert(iter != m_t_to_id.end());
156  return iter->second;
157  }
158 
166  const T &get_val(Idx i) const {
167 #ifdef NDEBUG
168  return m_id_to_t[i];
169 #else
170  return m_id_to_t.at(i);
171 #endif
172  }
173 
179  std::size_t size() const { return m_id_to_t.size(); }
180 
188  Idx add(const T &t) {
189  assert(m_t_to_id.find(t) == m_t_to_id.end());
190  Idx idx = size();
191  m_t_to_id[t] = idx;
192  m_id_to_t.push_back(t);
193  return idx;
194  }
195 
201  std::pair<Iterator, Iterator> get_range() const {
202  return std::make_pair(m_t_to_id.begin(), m_t_to_id.end());
203  }
204 
205  protected:
207  std::vector<T> m_id_to_t;
209  TToID m_t_to_id;
210 };
211 
218 template <typename T, typename Idx = int>
219 class eraseable_bimap : public bimap<T, Idx> {
220  typedef bimap<T, Idx> base;
221  using base::m_t_to_id;
222  using base::m_id_to_t;
223 
224  public:
230  void erase(const T &t) {
231  auto iter = m_t_to_id.find(t);
232  assert(iter != m_t_to_id.end());
233  Idx idx = iter->second;
234  m_t_to_id.erase(iter);
235  m_id_to_t.erase(m_id_to_t.begin() + idx);
236 
237  for (int i : irange(idx, Idx(m_id_to_t.size()))) {
238  assert(m_t_to_id.at(m_id_to_t[i]) == i + 1);
239  m_t_to_id[m_id_to_t[i]] = i;
240  }
241  }
242 };
243 
251 template <typename T, typename Idx = int> class bimap_of_consecutive {
252  // TODO maybe it should be passed but only on debug
253  static const Idx INVALID_IDX = -1;
254 
255  public:
256  static_assert(std::is_integral<T>::value, "Type T has to be integral");
257  bimap_of_consecutive() = default;
258 
266  template <typename Iter> bimap_of_consecutive(Iter b, Iter e) {
267  if (b == e) return;
268 
269  std::size_t size = std::distance(b, e);
270  m_id_to_t.resize(size);
271  std::copy(b, e, m_id_to_t.begin());
272 
273  m_t_to_id.resize(size, INVALID_IDX);
274  rank(m_id_to_t, m_t_to_id, INVALID_IDX);
275  }
276 
284  Idx get_idx(const T &t) const { return m_t_to_id[t]; }
285 
293  const T &get_val(Idx i) const { return m_id_to_t[i]; }
294 
300  std::size_t size() const { return m_id_to_t.size(); }
301 
302  private:
303  std::vector<T> m_id_to_t;
304  std::vector<Idx> m_t_to_id;
305 };
306 
313 template <typename ValT, typename IdxT> struct bimap_traits<bimap<ValT, IdxT>> {
314  typedef ValT Val;
315  typedef IdxT Idx;
316 };
317 
324 template <typename ValT, typename IdxT>
325 struct bimap_traits<eraseable_bimap<ValT, IdxT>> {
326  typedef ValT Val;
327  typedef IdxT Idx;
328 };
329 
336 template <typename ValT, typename IdxT>
337 struct bimap_traits<bimap_of_consecutive<ValT, IdxT>> {
338  typedef ValT Val;
339  typedef IdxT Idx;
340 };
341 
348 template <typename ValT, typename IdxT>
349 struct bimap_traits<bimap_mic<ValT, IdxT>> {
350  typedef ValT Val;
351  typedef IdxT Idx;
352 };
353 
363 template <typename T, typename Idx = int>
364 void rank(std::vector<T> const &m_id_to_t, std::vector<Idx> &m_t_to_id,
365  int INVALID_IDX = 0) {
366  static_assert(std::is_integral<T>::value, "Type T has to be integral");
367  unsigned long size = m_t_to_id.size();
368  for (auto i : irange(size)) {
369  Idx &idx = m_t_to_id[m_id_to_t[i]];
370  assert(m_id_to_t[i] < int(size) && idx == INVALID_IDX);
371  idx = i;
372  }
373 }
374 
375 }
376 }
377 #endif // PAAL_BIMAP_HPP
std::vector< T > m_id_to_t
mapping from id to element
Definition: bimap.hpp:207
const T & get_val(Idx i) const
get element on index i
Definition: bimap.hpp:78
TToID m_t_to_id
mapping from elements to ids
Definition: bimap.hpp:209
implements both sides mapping from the collection to (0,size(collection)) interval.
Definition: bimap.hpp:123
Idx get_idx(const T &t) const
get_idx on element t
Definition: bimap.hpp:66
std::size_t size() const
number of elements
Definition: bimap.hpp:91
Idx get_idx(const T &t) const
gets index of element t
Definition: bimap.hpp:153
Idx get_idx(const T &t) const
gets index of element t
Definition: bimap.hpp:284
const T & get_val(Idx i) const
get value for index i
Definition: bimap.hpp:166
Computes size of TypesVector.
std::size_t size() const
number of elements
Definition: bimap.hpp:300
the same as Bimap, but implemented using boost::multi_index_container. Unfortunately slower ...
Definition: bimap.hpp:40
std::size_t size() const
number of elements
Definition: bimap.hpp:179
const T & get_val(Idx i) const
gets value for index i
Definition: bimap.hpp:293
Idx add(const T &t)
adds element to collection
Definition: bimap.hpp:188
auto irange(T begin, T end)
irange
Definition: irange.hpp:22
bimap_mic(Range &&range)
constructor
Definition: bimap.hpp:51
Idx add(const T &t)
adds alement to bimap
Definition: bimap.hpp:100
in this bimap we know that elements forms permutation this allows optimization
Definition: bimap.hpp:251
std::pair< Iterator, Iterator > get_range() const
get range of all element, index pairs
Definition: bimap.hpp:201
void erase(const T &t)
erases element (takes linear time)
Definition: bimap.hpp:230
bimap(Range &&range)
constructor
Definition: bimap.hpp:137
this maps support erasing elements, Alert inefficient!!
Definition: bimap.hpp:219
bimap_of_consecutive(Iter b, Iter e)
constructor
Definition: bimap.hpp:266
void rank(std::vector< T > const &m_id_to_t, std::vector< Idx > &m_t_to_id, int INVALID_IDX=0)
computes rank i.e. index of element in range
Definition: bimap.hpp:364