All Classes Namespaces Files Functions Variables Typedefs Enumerations Friends Macros Pages
simple_cycle.hpp
Go to the documentation of this file.
1 //=======================================================================
2 // Copyright (c) 2013 Piotr Wygocki
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See
5 // accompanying file LICENSE_1_0.txt or copy at
6 // http://www.boost.org/LICENSE_1_0.txt)
7 //=======================================================================
16 #ifndef PAAL_SIMPLE_CYCLE_HPP
17 #define PAAL_SIMPLE_CYCLE_HPP
18 
20 
21 #include <cassert>
22 #include <vector>
23 #include <iterator>
24 
25 namespace paal {
26 namespace data_structures {
27 
36 template <typename CycleEl, typename IdxT = int> class simple_cycle {
37  public:
38  using cycle_el_pair = std::pair<CycleEl, CycleEl>;
39  using cycle_element = CycleEl;
40 
48  template <typename Iter> simple_cycle(Iter begin, Iter end) {
49  if (begin == end) {
50  return;
51  }
52 
53  std::size_t size = std::distance(begin, end);
54 
55  m_predecessor_map.reserve(size);
56  m_successor_map.reserve(size);
57 
58  IdxT prev_idx = add(*(begin++));
59  IdxT firstIdx = prev_idx;
60  for (; begin != end; ++begin) {
61  IdxT lastIdx = add(*begin);
62  link(prev_idx, lastIdx);
63  prev_idx = lastIdx;
64  }
65  link(prev_idx, firstIdx);
66  }
67 
70  void flip(const CycleEl &begin, const CycleEl &end) {
71  IdxT e1 = to_idx(begin);
72  IdxT b1 = prev_idx(e1);
73  IdxT b2 = to_idx(end);
74  IdxT e2 = next_idx(b2);
75 
76  partial_reverse(b2, e1);
77  link(b1, b2);
78  link(e1, e2);
79  }
80 
86  std::size_t size() const { return m_predecessor_map.size(); }
87 
95  CycleEl next(const CycleEl &ce) const {
96  return from_idx(next_idx(to_idx(ce)));
97  }
98 
99  // TODO use iterator_fascade
104  : public std::iterator<std::forward_iterator_tag, CycleEl, ptrdiff_t,
105  CycleEl *, const CycleEl &> {
106  public:
107 
114  vertex_iterator(const simple_cycle &cm, CycleEl ce)
115  : m_cycle(&cm), m_idx(m_cycle->to_idx(ce)), m_first(m_idx) {}
116 
120  vertex_iterator() : m_cycle(NULL), m_idx(-1) {}
121 
128  m_idx = next_idx(m_idx);
129 
130  if (m_idx == m_first) {
131  m_idx = -1;
132  }
133 
134  return *this;
135  }
136 
143  vertex_iterator i(*this);
144  operator++();
145  return i;
146  }
147 
155  bool operator!=(vertex_iterator ei) const { return !operator==(ei); }
156 
164  bool operator==(vertex_iterator ei) const { return m_idx == ei.m_idx; }
165 
171  const CycleEl *const operator->() const { return &operator*(); }
172 
178  const CycleEl &operator*() const { return m_cycle->from_idx(m_idx); }
179 
180  private:
181 
189  IdxT next_idx(IdxT i) const { return m_cycle->next_idx(i); }
190 
191  const simple_cycle *m_cycle;
192  IdxT m_idx;
193  IdxT m_first;
194  };
195 
196  using vertices = boost::iterator_range<vertex_iterator>;
197 
205  vertex_iterator vbegin(const CycleEl &el) const {
206  return vertex_iterator(*this, el);
207  }
208 
214  vertex_iterator vbegin() const { return vbegin(from_idx(0)); }
215 
221  vertex_iterator vend() const { return vertex_iterator(); }
222 
230  vertices get_vertices_range(const CycleEl &el) const {
231  return vertices(vbegin(el), vend());
232  }
233 
239  vertices get_vertices_range() const {
240  return get_vertices_range(from_idx(0));
241  }
242 
243  // TODO use iterator_fascade
248  : public std::iterator<std::forward_iterator_tag, cycle_el_pair,
249  ptrdiff_t, cycle_el_pair *, const cycle_el_pair &> {
250  public:
257  edge_iterator(const simple_cycle &cm, CycleEl ce)
258  : m_cycle(&cm), m_idx(m_cycle->to_idx(ce)), m_first(m_idx) {
259 
260  move_curr();
261  }
262 
266  edge_iterator() : m_cycle(NULL), m_idx(-1) {}
267 
274  m_idx = next_idx(m_idx);
275  move_curr();
276 
277  if (m_idx == m_first) {
278  m_idx = -1;
279  }
280 
281  return *this;
282  }
283 
290  edge_iterator i(*this);
291  operator++();
292  return i;
293  }
294 
302  bool operator!=(edge_iterator ei) const { return !operator==(ei); }
303 
311  bool operator==(edge_iterator ei) const { return m_idx == ei.m_idx; }
312 
318  const cycle_el_pair *const operator->() const { return &m_curr; }
319 
325  const cycle_el_pair &operator*() const { return m_curr; }
326 
327  private:
331  void move_curr() {
332  m_curr.first = m_cycle->from_idx(m_idx);
333  m_curr.second = m_cycle->from_idx(next_idx(m_idx));
334  }
335 
343  IdxT next_idx(IdxT i) const { return m_cycle->next_idx(i); }
344 
345  const simple_cycle *m_cycle;
346  IdxT m_idx;
347  IdxT m_first;
348  cycle_el_pair m_curr;
349  };
350 
351  using edges = boost::iterator_range<edge_iterator>;
352 
360  edges get_edge_range(const CycleEl &el) const {
361  return edges(edge_iterator(*this, el), edge_iterator());
362  }
363 
369  edges get_edge_range() const {
370  return get_edge_range(from_idx(0));
371  }
372 
373  protected:
380  void link(IdxT x, IdxT y) {
381  m_successor_map[x] = y;
382  m_predecessor_map[y] = x;
383  }
384 
392  void partial_reverse(IdxT x, IdxT y) {
393  if (x == y) return;
394  IdxT t_next = prev_idx(x);
395  IdxT t;
396  do {
397  t = t_next;
398  t_next = prev_idx(t);
399  link(x, t);
400  x = t;
401  } while (t != y);
402  }
403 
411  IdxT to_idx(const CycleEl &ce) const { return m_cycle_idx.get_idx(ce); }
412 
420  IdxT next_idx(IdxT i) const { return m_successor_map[i]; }
421 
429  IdxT prev_idx(IdxT i) const { return m_predecessor_map[i]; }
430 
438  const CycleEl &from_idx(IdxT i) const { return m_cycle_idx.get_val(i); }
439 
447  IdxT add(const CycleEl &el) {
448  m_predecessor_map.push_back(-1);
449  m_successor_map.push_back(-1);
450  return m_cycle_idx.add(el);
451  }
452 
455 
456  using SorsMap = std::vector<IdxT>;
457 
462 };
463 
470 template <typename CycleEl, typename IdxT = int>
471 class Simplecycle_start_from_last_change : public simple_cycle<CycleEl, IdxT> {
473 
474  public:
482  template <typename Iter>
484  : Base(b, e), m_last_id(0) {}
485 
492  void flip(const CycleEl &begin, const CycleEl &end) {
493  IdxT e1 = to_idx(begin);
494  m_last_id = prev_idx(e1);
495  Base::flip(begin, end);
496  }
497 
503  typename Base::vertex_iterator vbegin() const {
504  return Base::vbegin(from_idx(m_last_id));
505  }
506 
507  private:
508  IdxT m_last_id;
509 };
510 
511 } // data_structures
512 } // paal
513 
514 #endif // PAAL_SIMPLE_CYCLE_HPP
IdxT next_idx(IdxT i) const
returns next idx in the cycle
This is the simplest implementation of the Cycle concept based on the list.
const CycleEl & operator*() const
operator*()
bool operator==(vertex_iterator ei) const
operator==
vertex_iterator(const simple_cycle &cm, CycleEl ce)
constructor
Base::vertex_iterator vbegin() const
vbegin starts from last flip position
Idx get_idx(const T &t) const
gets index of element t
Definition: bimap.hpp:153
void flip(const CycleEl &begin, const CycleEl &end)
IdxT prev_idx(IdxT i) const
returns previous idx
edges get_edge_range() const
returns edges range
const T & get_val(Idx i) const
get value for index i
Definition: bimap.hpp:166
IdxT add(const CycleEl &el)
ads new element to cycle data structures
edge_iterator(const simple_cycle &cm, CycleEl ce)
constructor
const CycleEl *const operator->() const
operator-&gt;()
Computes size of TypesVector.
vertices get_vertices_range(const CycleEl &el) const
returns range of vertices starting at el
bool operator!=(edge_iterator ei) const
operator!=
vertices get_vertices_range() const
returns range of vertices
Idx add(const T &t)
adds element to collection
Definition: bimap.hpp:188
CycleEl next(const CycleEl &ce) const
next element in the cycle
iterator over vertices of the cycle
void link(IdxT x, IdxT y)
connects two vertices represented by ids
this class adapts Simple cycle to start from last changed position
const cycle_el_pair & operator*() const
operator*()
vertex_iterator operator++(int)
operator++(int)
bool operator==(edge_iterator ei) const
operator==
void flip(const CycleEl &begin, const CycleEl &end)
flip remembers last changed position
bool operator!=(vertex_iterator ei) const
operator!=
IdxT to_idx(const CycleEl &ce) const
vertex to idx
edges get_edge_range(const CycleEl &el) const
returns edges range starting at el
const CycleEl & from_idx(IdxT i) const
idx to vertex
vertex_iterator vend() const
end of the vertices range
vertex_iterator vbegin(const CycleEl &el) const
begin of the vertices range starting at el
simple_cycle(Iter begin, Iter end)
constructor
void partial_reverse(IdxT x, IdxT y)
after this operation links from x to y are connected i reverse order, after this function call cycle ...
const cycle_el_pair *const operator->() const
operator-&gt;
edge_iterator operator++(int)
operator++(int)
vertex_iterator vbegin() const
begin of the vertices range
bimap< CycleEl, IdxT > m_cycle_idx
mapping from elements to indexes
SorsMap m_predecessor_map
predecessors
std::size_t size() const
number of elements in the cycle