source: trunk/GDE/SINA/builddir/src/graph.h

Last change on this file was 19170, checked in by westram, 2 years ago
  • sina source
    • unpack + remove tarball
    • no longer ignore sina builddir.
File size: 12.5 KB
Line 
1/*
2Copyright (c) 2006-2018 Elmar Pruesse <elmar.pruesse@ucdenver.edu>
3
4This file is part of SINA.
5SINA is free software: you can redistribute it and/or modify it under
6the terms of the GNU General Public License as published by the Free
7Software Foundation, either version 3 of the License, or (at your
8option) any later version.
9
10SINA is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or
12FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13for more details.
14
15You should have received a copy of the GNU General Public License
16along with SINA.  If not, see <http://www.gnu.org/licenses/>.
17
18Additional permission under GNU GPL version 3 section 7
19
20If you modify SINA, or any covered work, by linking or combining it
21with components of ARB (or a modified version of that software),
22containing parts covered by the terms of the
23ARB-public-library-license, the licensors of SINA grant you additional
24permission to convey the resulting work. Corresponding Source for a
25non-source form of such a combination shall include the source code
26for the parts of ARB used as well as that of the covered work.
27*/
28
29// template classes for bidirectional graph as simple container
30// nodes know previous and next nodes, edges are implicit
31// insert() adds node, link() creates an edge
32
33#ifndef _GRAPH_H_
34#define _GRAPH_H_
35
36#include <vector>
37#include <list>
38#include <iostream>
39#include <iterator>
40#include <algorithm>
41
42template<typename T> class dag_node;
43
44template<typename T>
45class dag
46{
47public:
48    class iterator;
49    class pn_iterator;
50
51    using value_type = T;
52    using pointer = T *;
53    using reference = T &;
54
55    using node_type = dag_node<T>;
56    using node_container = std::list<node_type>;
57    using node_ref = typename node_container::iterator;
58    using const_node_ref = typename node_container::const_iterator;
59    using idx_type = unsigned int;
60
61    dag() : _nodes()
62    {
63         // ewww ... this is hacky! FIXME
64        _nodes.push_back(node_type(T(0,'.'),-1));
65        _begin=_nodes.begin();
66    }
67
68    void link(node_ref a, node_ref b);
69    void link(iterator a, iterator b);
70
71    iterator insert(T a);
72    iterator begin();
73    iterator end();
74
75    pn_iterator pn_first_begin();
76    pn_iterator pn_first_end();
77    pn_iterator pn_last_begin();
78    pn_iterator pn_last_end();
79
80
81    template<typename C> void sort(C& comp);
82    void sort(); 
83    void reduce_edges();
84
85    const T& getById(idx_type idx) const {
86        auto it=_nodes.begin(), end=_nodes.end();
87        while (it != end && it->_id != idx ) {
88            ++it;
89        }
90#ifdef DEBUG
91        if (it == end) {
92            logger->critical("ARG234: {}", idx);
93            exit(1);
94        }
95#endif
96        return it->data;
97    }
98
99    unsigned int size() const { return _nodes_size; };
100
101    void print_graphviz(std::ostream& out, const char* name);
102
103//protected:
104    node_container _nodes;
105    node_ref _begin;
106    unsigned int _nodes_size{0};
107};
108
109template<typename T>
110std::ostream&
111operator<<(std::ostream& out, dag<T> d) {
112    std::copy(d.begin(), d.end(), std::ostream_iterator<T>(out,","));
113    return out;
114}
115
116template<typename T> struct fix_idx;
117
118template<typename T>
119class dag_node
120{
121public:
122    using node_type = typename dag<T>::node_type;
123    using node_ref = typename dag<T>::node_ref;
124    using node_ref_container = std::list<node_ref>;
125
126    dag_node(T t, unsigned int id) : data(t),_id(id) {}
127
128    T data;
129
130    bool operator<(const dag_node& other) const {
131      // FIXME
132      //return data < other.data;
133      return _id < other._id;
134    }
135    bool operator==(const dag_node& other) const {
136        return data == other.data;
137    }
138
139    unsigned int id() const {return _id;}
140
141    node_ref_container _previous;
142    node_ref_container _next;
143    unsigned int _id;
144};
145
146template<typename T>
147std::ostream&
148operator<<(std::ostream& out, dag_node<T> dag_node) {
149    out << dag_node.data;
150    return out;
151}
152
153// Iterator
154
155template<typename T>
156class dag<T>::pn_iterator {
157public:
158    using reference = T &;
159    using value_type = T;
160    using pointer = T *;
161    using _container = dag<T>;
162    using _self = typename dag<T>::pn_iterator;
163
164    using node_ref_it = typename dag_node<T>::node_ref_container::iterator;
165
166    explicit pn_iterator(const node_ref_it& nri) : _iter(nri) {}
167
168    bool operator!=(const pn_iterator& i) const { return _iter != i._iter; }
169    bool operator==(const pn_iterator& i) const { return !(*this != i); }
170
171    dag_node<T>& get_node() const { return *(*_iter); }
172    _self& operator++() { ++_iter; return *this; }
173
174    reference operator*() { return get_node().data; }
175    pointer operator->() { return &(get_node().data); }
176
177private:
178    node_ref_it _iter;
179};
180
181
182
183template<typename T>
184class dag<T>::iterator {
185public:
186    using reference = T &;
187    using value_type = T;
188    using pointer = T *;
189    using iterator_category = typename node_ref::iterator_category;
190    using difference_type = int;
191
192
193    using dag_t = dag<T>;
194    friend class dag<T>;
195
196    explicit iterator(node_ref idx) : _idx(idx), _isNull(false) {}
197    iterator(const iterator& orig) : _idx(orig._idx), _isNull(false) {}
198    iterator() = default;
199
200    dag_node<T>& get_node() const { return *_idx; }
201    node_ref get_node_ref() const { return _idx; }
202
203    iterator& operator++() { ++_idx; return *this; }
204    iterator& operator--() { --_idx; return *this; }
205
206    bool operator!=(const iterator& i) const { return _idx!=i._idx; }
207    bool operator==(const iterator& i) const { return _idx==i._idx; }
208    bool operator<(const iterator& i) const { return _idx<i._idx; }
209    bool isNull() const { return _isNull; }
210
211    using pn_iterator = typename dag<T>::pn_iterator;
212
213    pn_iterator prev_begin() const {
214        return pn_iterator(get_node()._previous.begin());
215    }
216    pn_iterator prev_end() const {
217        return pn_iterator(get_node()._previous.end());
218    }
219    pn_iterator next_begin() const {
220        return pn_iterator(get_node()._next.begin());
221    }
222    pn_iterator next_end() const {
223        return pn_iterator(get_node()._next.end());
224    }
225
226    reference operator*() { return get_node().data; }
227    pointer operator->() { return &(get_node().data); }
228//protected:
229    node_ref _idx;
230    bool     _isNull{true};
231};
232
233template<typename T>
234inline typename dag<T>::pn_iterator
235prev_begin(const dag<T>& /*unused*/, const typename dag<T>::iterator& i)
236{
237  return i.prev_begin();
238}
239
240template<typename T>
241inline typename dag<T>::pn_iterator
242prev_end(const dag<T>& /*unused*/, const typename dag<T>::iterator& i)
243{
244  return i.prev_end();
245}
246
247template<typename T>
248inline typename dag<T>::pn_iterator
249next_begin(const dag<T>& /*unused*/, const typename dag<T>::iterator& i)
250{
251  return i.next_begin();
252}
253
254template<typename T>
255inline typename dag<T>::pn_iterator
256next_end(const dag<T>& /*unused*/, const typename dag<T>::iterator& i)
257{
258  return i.next_end();
259}
260
261template<typename T>
262inline const typename dag<T>::idx_type
263get_node_id(const dag<T>& /*unused*/, typename dag<T>::iterator i) {
264    return i.get_node().id();
265}
266
267template<typename T>
268inline const typename dag<T>::idx_type
269get_node_id(const dag<T>& /*unused*/, typename dag<T>::pn_iterator i) {
270    return i.get_node().id();
271}
272
273template<typename S, typename T>
274S
275for_each_prev(T& git, S s) {
276    using node_ref = typename T::dag_t::node_ref;
277    using pn_iterator = typename std::list<node_ref>::iterator;
278    pn_iterator it = git.get_node()._previous.begin();
279    pn_iterator end = git.get_node()._previous.end();
280    for(; it != end; ++it) {
281        s(*it);
282    }
283    return s;
284}
285
286
287template<typename T>
288typename dag<T>::iterator
289dag<T>::begin()
290{
291    return iterator(++_nodes.begin());
292}
293
294template<typename T>
295typename dag<T>::iterator
296dag<T>::end()
297{
298    return iterator(_nodes.end());
299}
300
301template<typename T>
302typename dag<T>::pn_iterator
303dag<T>::pn_first_begin()
304{
305    return pn_iterator(_nodes.begin()->_next.begin());
306}
307
308template<typename T>
309typename dag<T>::pn_iterator
310dag<T>::pn_first_end()
311{
312    return pn_iterator(_nodes.begin()->_next.end());
313}
314
315template<typename T>
316typename dag<T>::pn_iterator
317dag<T>::pn_last_begin()
318{
319    return pn_iterator(_nodes.begin()->_previous.begin());
320}
321
322template<typename T>
323typename dag<T>::pn_iterator
324dag<T>::pn_last_end()
325{
326    return pn_iterator(_nodes.begin()->_previous.end());
327}
328
329
330// Implementations:
331
332template<typename T>
333void
334dag<T>::link(node_ref a, node_ref b)
335{
336    a->_next.push_back(b);
337    b->_previous.push_back(a);
338    _nodes.begin()->_previous.remove(a);
339    _nodes.begin()->_next.remove(b);
340}
341
342template<typename T>
343void
344dag<T>::link(iterator a, iterator b)
345{
346    link(a._idx,b._idx);
347}
348
349template<typename T>
350typename dag<T>::iterator
351dag<T>::insert(T a) {
352    auto it = _nodes.insert(_nodes.end(), node_type(a, _nodes_size++));
353    _nodes.begin()->_next.push_back(it);
354    _nodes.begin()->_previous.push_back(it);
355
356    return iterator(it);
357}
358
359template<typename T>
360void
361dag<T>::print_graphviz(std::ostream& out, const char* name)
362{
363    out << "digraph " << name << " { " << std::endl;
364    out << "rotate=90" << std::endl;
365
366    auto it   = _nodes.begin();
367    auto iend = _nodes.end();
368
369    for (;it != iend; ++it) {
370        out << "n" << it->id() << " [ label = \""
371            << it->data
372            << "\" ]; ";
373
374        {
375            auto jt   = it->_next.begin();
376            auto jend = it->_next.end();
377            for (;  jt != it->_next.end(); ++jt) {
378                out << "n" << it->id() << " -> n" << (*jt)->id() << "; ";
379            }
380        }
381        /*
382        out << " // ";
383        {
384            auto jt   = it->_previous.begin();
385            auto jend = it->_previous.end();
386            for (;  jt != it->_previous.end(); ++jt) {
387                out << "n" << it->id() << " -> n" << (*jt)->id() << "; ";
388            }
389        }
390        */
391        out << std::endl;
392    }
393    out << "}" << std::endl;
394}
395
396// *** Sorting (reorders nodes in vector) ***
397
398template<typename F>
399struct dereference {
400    explicit dereference(F f) : _f(f){}
401    dereference() : _f(){}
402    using result_type = typename F::result_type;
403
404    template<typename A, typename B>
405    result_type operator()(const A& a,
406                           const B& b) {
407        return _f(*a, *b);
408    }
409    F _f;
410};
411
412// default ordering: use operator< on T
413template<typename T, typename F>
414struct by_data {
415    explicit by_data(F f) : _f(f){}
416    bool operator()(const dag_node<T>& a, const dag_node<T>& b) {
417        return _f(a.data,b.data);
418    }
419    F _f;
420};
421
422
423// maps old idx to new idx using lookup vector
424template<typename node_ref>
425struct lookup {
426    explicit lookup(std::vector<node_ref> &nrv) : _nrv(nrv) {}
427    node_ref operator()(node_ref nr) {
428        return _nrv[nr];
429    }
430    std::vector<node_ref>& _nrv;
431};
432
433// fixes node_references of given node using lookup vector
434template<typename T>
435struct fix_idx {
436    using node_ref = typename dag<T>::node_ref;
437    explicit fix_idx(std::vector<node_ref> &nrv) : _nrv(nrv) {}
438    void operator()(dag_node<T>& dn) {
439        // fix incoming edges
440        std::transform(dn._previous.begin(),dn._previous.end(),
441                       dn._previous.begin(),lookup<node_ref>(_nrv));
442        // fix outgoing edges
443        std::transform(dn._next.begin(),dn._next.end(),
444                       dn._next.begin(),lookup<node_ref>(_nrv));
445        // fix self "pointer"
446        dn._self = _nrv[dn._self];
447    }
448    std::vector<node_ref>& _nrv;
449};
450
451template<typename T> template<typename C>
452void
453dag<T>::sort(C& comp) {
454  // sort nodes using given comparator
455  _nodes.sort(by_data<T,C>(comp));
456}
457
458template<typename T> 
459void 
460dag<T>::sort() { 
461  std::less<T> c; 
462  sort(c); 
463}
464
465// reduce_edges() [ removes duplicate edges from nodes ]
466template<typename T>
467struct reduce_edge {
468  using node_type = typename dag<T>::node_type;
469  using node_ref = typename dag<T>::node_ref;
470  void
471  operator()(node_type& node) {
472    node._previous.sort(dereference<std::less<node_type> >());
473    node._previous.erase(unique(node._previous.begin(),
474                                node._previous.end()),
475                         node._previous.end());
476   
477    node._next.sort(dereference<std::less<node_type> >());
478    node._next.erase(unique(node._next.begin(),
479                            node._next.end()),
480                     node._next.end());
481  }
482};
483
484template<typename T>
485void
486dag<T>::reduce_edges() {
487    for_each(_nodes.begin(),_nodes.end(), reduce_edge<T>());
488}
489
490
491#endif
492/*
493  Local Variables:
494  mode:c++
495  c-file-style:"stroustrup"
496  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
497  indent-tabs-mode:nil
498  fill-column:99
499  End:
500*/
501// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
502
503
504
505
Note: See TracBrowser for help on using the repository browser.