ug4
sparsematrix_boost.h
Go to the documentation of this file.
1 /* Copyright (c) 2022: G-CSC, Goethe University Frankfurt
2  * Felix Salfelder 2022
3  * This file is part of UG4.
4  *
5  * UG4 is free software: you can redistribute it and/or modify it under the
6  * terms of the GNU Lesser General Public License version 3 (as published by the
7  * Free Software Foundation) with the following additional attribution
8  * requirements (according to LGPL/GPL v3 ยง7):
9  */
10 
11 // BGL interface for cpu sparse martrix (dynamic CRS).
12 
13 #ifndef UG_SPARSEMATRIX_BOOST_H
14 #define UG_SPARSEMATRIX_BOOST_H
15 
16 #include "common/util/trace.h"
18 
19 #include <boost/graph/properties.hpp> // put_get_helper
20 #include <boost/iterator/counting_iterator.hpp>
21 
22 #include <cstdint> // for std::intmax_t
23 
24 namespace boost{
25 
26 using ug::iszero; // for now
27 
28 // a bit of a pointer dance,
29 // because ug::SparseMatrix<T>::const_row_iterator is not default constructible.
30 template<class T>
31 class SM_adjacency_iterator : public iterator_facade<
32  SM_adjacency_iterator<T>,
33  typename ug::SparseMatrix<T>::const_row_iterator,
34  std::input_iterator_tag,
35  size_t, // <= reference
36  std::intmax_t // difference_type
37  >{ //
39  typedef typename M::const_row_iterator iter_t;
40  typedef iterator_facade<
43  std::input_iterator_tag,
44  size_t, // <= reference
45  std::intmax_t // difference_type
47 
48 public:
49  typedef iter_t* value_type;
50  typedef intmax_t difference_type;
51  typedef size_t reference;
52 
53 public:
54  SM_adjacency_iterator() : base_class(), _base(nullptr), _end(nullptr){
55  }
58  : _base(p._base?(new iter_t(*p._base)) : nullptr)
59  , _end(p._end?(new iter_t(*p._end)) : nullptr){
60  }
62  assert(p);
63  _base = new iter_t(*p);
64  _end = new iter_t(*e);
65  skip_zeroes();
66  }
68  delete _base;
69  delete _end;
70  _base = nullptr;
71  _end = nullptr;
72  }
75  if(other._base){
76  delete _base;
77  _base = new iter_t(*other._base);
78  }else{ untested();
79  _base = nullptr;
80  }
81  if(other._end){
82  delete _end;
83  _end = new iter_t(*other._end);
84  }else{ untested();
85  _end = nullptr;
86  }
87  return *this;
88  }
89 
90  T const& value() const {
91  assert(_base);
92  return _base->value();
93  }
94  int row() const {
95  assert(_base);
96  return _base->row();
97  }
98  size_t idx() const { untested();
99  assert(_base);
100  return _base->idx();
101  }
103  assert(_base);
104  return _base->index(); // row?
105  }
106  bool operator==(const SM_adjacency_iterator& other) const {
107  assert(_base);
108  assert(other._base);
109  return *_base == *other._base;
110  }
111  bool operator!=(const SM_adjacency_iterator& other) const {
112  assert(_base);
113  assert(other._base);
114  return *_base != *other._base;
115  }
116 
117 private:
118  // could use boost::filter_iterator, but does not work yet.
119  void skip_zeroes(){
120  while((*_base) != (*_end)){
121  if(iszero(_base->value())){
122  ++(*_base);
123  }else{
124  break;
125  }
126  }
127  }
128  bool equal(SM_adjacency_iterator const& other) const { untested();
129  assert(_base);
130  assert(other._base);
131  return *_base == *other._base;
132  }
133  void increment() {
134  assert(_base);
135  assert(_end);
136  ++(*_base);
137  skip_zeroes();
138  }
139  void decrement() { untested();
140  // incomplete(); // don't use. too complicated.
141  assert(_base);
142  --(*_base);
143  }
144 
145 private:
148  friend class iterator_core_access;
149 }; // SM_adjacency_iterator
150 
151 template<class T>
152 class SM_edge{
153 public:
154 // SM_edge(size_t v, size_t w) : _row(v), _idx(w) { untested();
155 // }
156  SM_edge(SM_edge const&) = default;
157  SM_edge(SM_edge&&) = default;
158  explicit SM_edge() { untested();
159  }
160  SM_edge(int s, int t, T const& v) : _source(s), _target(t), _value(v) {
161  }
162  SM_edge& operator=(SM_edge const&) = default;
163  SM_edge& operator=(SM_edge&&) = default;
164 
165 public:
166  int source() const{
167  return _source;
168  }
169  int target() const{
170  return _target;
171  }
172  template<class X>
173  T const& value(X const&) const{
174  return _value;
175  }
176 
177 public:
178  bool operator==(const SM_edge& other) const { untested();
179  return _source == other._source && _target == other._target;
180  }
181  bool operator!=(const SM_edge& other) const { untested();
182  return !operator==(other);
183  }
184 
185 private:
186  int _source;
187  int _target;
189 }; // SM_edge
190 
191 template<class T, class M>
192 int source(SM_edge<T> const& e, M const&)
193 { untested();
194  return e.source();
195 }
196 
197 template<class T, class M>
198 int target(SM_edge<T> const& e, M const&)
199 { untested();
200  return e.target();
201 }
202 
203 template<class T, bool out=true>
204 class SM_out_edge_iterator : public iterator_facade<
205  SM_out_edge_iterator<T, out>,
206  SM_adjacency_iterator<T>,
207  // bidirectional_traversal_tag, // breaks InputIterator (why?)
208  std::input_iterator_tag,
209  SM_edge<T>, // <= reference
210  std::intmax_t // difference_type
211  >{ //
212 public: // types
213  typedef iterator_facade<
216  std::input_iterator_tag,
217  SM_edge<T>, // <= reference
218  std::intmax_t // difference_type
222  typedef intmax_t difference_type;
225 
226 public: // construct
228  }
230  : base_class(), _base(w), _src(src) {
231  if(out){
232  }else{
233  }
234  }
236  : base_class(p), _base(p._base), _src(p._src){
237  if(out){
238  }else{
239  }
240  }
243  }
246 #if 0
247 public: // op
248  SM_out_edge_iterator operator+(int a) const{ untested();
249  SM_out_edge_iterator ret(*this);
250  ret.base.first += a;
251  return ret;
252  }
253  SM_out_edge_iterator operator-(int a) const{ untested();
254  SM_out_edge_iterator ret(*this);
255  ret.base.first -= a;
256  return ret;
257  }
259  SM_out_edge_iterator ret(*this);
260  return ret.base.first - other.base.first;
261  }
262 #endif
263 private:
265  if(out){
266  return edge_type(_src, *_base, _base.value());
267  }else{
268  return edge_type(*_base, _src, _base.value());
269  }
270  }
271  bool equal(SM_out_edge_iterator const& other) const { untested();
272  assert(_base.first == other._base.first);
273  return _base.second == other._base.second;
274  }
275  void increment() { untested();
276  ++_base;
277  }
278  void decrement() { untested();
279  --_base;
280  }
281  // bool operator==(const SM_out_edge_iterator& other) const
282  // { incomplete();
283  // return false;
284  // }
285 public:
287  ++_base;
288  return *this;
289  }
291  SM_out_edge_iterator copy(*this);
292  ++*this;
293  return copy;
294  }
295  bool operator==(const SM_out_edge_iterator& other) const {
296  return _base == other._base;
297  }
298  bool operator!=(const SM_out_edge_iterator& other) const {
299  return _base != other._base;
300  }
301 
302 private:
304  int _src;
305  friend class iterator_core_access;
306 }; // SM_out_edge_iterator
307 
309  : adjacency_graph_tag, bidirectional_graph_tag, vertex_list_graph_tag {};
310 
311 template <class T> struct graph_traits<ug::SparseMatrix<T>>{
312  typedef int vertex_descriptor;
314  typedef directed_tag directed_category;
315  typedef disallow_parallel_edge_tag edge_parallel_category;
317  typedef counting_iterator<size_t> vertex_iterator;
320  typedef int degree_size_type;
321  typedef int vertices_size_type;
322 };
323 
324 template<class T>
325 std::pair<typename graph_traits<ug::SparseMatrix<T>>::adjacency_iterator,
326  typename graph_traits<ug::SparseMatrix<T>>::adjacency_iterator>
327 inline adjacent_vertices(size_t v, ug::SparseMatrix<T> const& M)
328 {
329  assert(v<M.num_rows());
330  typedef typename graph_traits<ug::SparseMatrix<T>>::adjacency_iterator a;
331 
334 
335  return std::make_pair(a(&b, &e), a(&e, &e));
336 }
337 
338 template<class T>
339 inline std::pair<SM_out_edge_iterator<T>, SM_out_edge_iterator<T>>
341 {
342  assert(size_t(v)<g.num_rows());
343  typedef SM_out_edge_iterator<T> Iter;
344  auto a = adjacent_vertices(v, g);
345  return std::make_pair(Iter(a.first, v), Iter(a.second, v));
346 }
347 
348 template<class T>
350  : public put_get_helper<size_t, sparse_matrix_index_map<T> > { //
351 public:
352  typedef size_t vertex_index_type;
353  typedef size_t vertex_descriptor;
354  typedef readable_property_map_tag category;
358 
360  }
361  sparse_matrix_index_map(ug::SparseMatrix<T>const&, boost::vertex_index_t) { untested();
362  }
363  template<class X>
365  }
366  template <class T_>
367  value_type operator[](T_ x) const {
368  return x;
369  }
371  return *this;
372  }
373 };
374 
375 template<class T>
376 struct property_map<ug::SparseMatrix<T>, vertex_index_t>{
378  typedef type const_type;
379 };
380 
381 template<class T>
382 typename property_map<ug::SparseMatrix<T>, vertex_index_t>::const_type
383 get(vertex_index_t, ug::SparseMatrix<T> const& m)
384 {
385  return sparse_matrix_index_map<T>(m);
386 }
387 
388 template<class T>
389 std::pair<counting_iterator<size_t>, counting_iterator<size_t> > vertices(
390  ug::SparseMatrix<T> const& M)
391 {
392  counting_iterator<size_t> b(0);
393  counting_iterator<size_t> e(M.num_rows());
394 
395  return std::make_pair(b,e);
396 }
397 
398 template<class T>
400 {
401  assert(M.num_rows() == M.num_cols());
402  return M.num_rows();
403 }
404 
405 template<class T>
406 int out_degree(int v, ug::SparseMatrix<T> const& M)
407 {
408  int c = 0;
409  auto i = out_edges(v, M);
410  for(; i.first != i.second; ++i.first) {
411  ++c;
412  }
413  return c;
414 }
415 
416 // template<class T>
417 // T get(edge_weight_t, ug::SparseMatrix<T> const& M, SM_edge<T> e)
418 // { untested();
419 // return e.value();
420 // }
421 
422 template<class T, class M=ug::SparseMatrix<T>>
424  public put_get_helper< T /*algebraic connection?*/, SM_edge_weight_map<T> > { //
425 public:
426  typedef T edge_weight_type;
427  typedef int vertex_descriptor;
428  typedef readable_property_map_tag category;
430  typedef T& reference;
432 
434  }
435  SM_edge_weight_map(ug::SparseMatrix<T>const & g, boost::edge_weight_t) : _g(g) { untested();
436  }
437  // bug?
438  SM_edge_weight_map(M const& g) : _g(g) {
439  }
440  template <class X>
441  value_type operator[](X const& x) const {
442  // assert(x == _g.position(x));
443  return x.value(_g);
444  }
446  assert(&s._g==&_g); (void)s;
447  return *this;
448  }
449 private:
450  M const& _g;
451 }; // SM_edge_weight_map
452 
453 // g++ 'enumeral_type' in template unification not implemented workaround
454 template<class T, class Tag>
455 struct property_map<ug::SparseMatrix<T>, Tag> {
456 // typedef typename gala_graph_property_map<Tag>::template bind_<T> map_gen;
457 // typedef typename map_gen::type type;
458 // typedef typename map_gen::const_type const_type;
459 };
460 
461 template<class T>
463 //inline typename property_map<ug::SparseMatrix<T>, edge_weight_t>::type
464 get(edge_weight_t, ug::SparseMatrix<T> const & g) {
465  return SM_edge_weight_map<T>(g);
466 }
467 
468 #if 0
469 template<class T>
470 inline typename property_map<ug::SparseMatrix<T>, edge_all_t>::type
471 get(edge_all_t, ug::SparseMatrix<T> & g) { incomplete();
472  typedef typename property_map<ug::SparseMatrix<T>, edge_all_t>::type
473  pmap_type;
474  return pmap_type(&g);
475 }
476 #endif
477 
478 } // boost
479 
480 namespace ug{
481 
482 // used from boost::print_graph, graph_utility.hpp.
483 // must be in ug, because of ADL. why don't they call boost::{out_edges,vertices}?
484 using boost::vertices;
485 using boost::out_edges;
486 
487 }// ug
488 
489 #endif // guard
parameterString p
parameterString s
Definition: sparsematrix_interface.h:37
Definition: sparsematrix_boost.h:37
bool operator==(const SM_adjacency_iterator &other) const
Definition: sparsematrix_boost.h:106
friend class iterator_core_access
Definition: sparsematrix_boost.h:148
SM_adjacency_iterator & operator=(SM_adjacency_iterator &&other)=delete
~SM_adjacency_iterator()
Definition: sparsematrix_boost.h:67
intmax_t difference_type
Definition: sparsematrix_boost.h:50
SM_adjacency_iterator(SM_adjacency_iterator &&p)=delete
void skip_zeroes()
Definition: sparsematrix_boost.h:119
T const & value() const
Definition: sparsematrix_boost.h:90
SM_adjacency_iterator(value_type p, value_type e)
Definition: sparsematrix_boost.h:61
void decrement()
Definition: sparsematrix_boost.h:139
value_type _end
Definition: sparsematrix_boost.h:147
iter_t * value_type
Definition: sparsematrix_boost.h:49
SM_adjacency_iterator & operator=(const SM_adjacency_iterator &other)
Definition: sparsematrix_boost.h:74
value_type _base
Definition: sparsematrix_boost.h:146
SM_adjacency_iterator()
Definition: sparsematrix_boost.h:54
ug::SparseMatrix< T > M
Definition: sparsematrix_boost.h:38
iterator_facade< SM_adjacency_iterator< T >, typename ug::SparseMatrix< T >::const_row_iterator, std::input_iterator_tag, size_t, std::intmax_t > base_class
Definition: sparsematrix_boost.h:46
bool equal(SM_adjacency_iterator const &other) const
Definition: sparsematrix_boost.h:128
int row() const
Definition: sparsematrix_boost.h:94
void increment()
Definition: sparsematrix_boost.h:133
SM_adjacency_iterator(SM_adjacency_iterator const &p)
Definition: sparsematrix_boost.h:57
M::const_row_iterator iter_t
Definition: sparsematrix_boost.h:39
bool operator!=(const SM_adjacency_iterator &other) const
Definition: sparsematrix_boost.h:111
reference dereference() const
Definition: sparsematrix_boost.h:102
size_t idx() const
Definition: sparsematrix_boost.h:98
size_t reference
Definition: sparsematrix_boost.h:51
Definition: sparsematrix_boost.h:424
int vertex_descriptor
Definition: sparsematrix_boost.h:427
SM_edge_weight_map(ug::SparseMatrix< T >const &g, boost::edge_weight_t)
Definition: sparsematrix_boost.h:435
T & reference
Definition: sparsematrix_boost.h:430
SM_edge_weight_map(M const &g)
Definition: sparsematrix_boost.h:438
vertex_descriptor key_type
Definition: sparsematrix_boost.h:431
edge_weight_type value_type
Definition: sparsematrix_boost.h:429
SM_edge_weight_map & operator=(const SM_edge_weight_map &s)
Definition: sparsematrix_boost.h:445
SM_edge_weight_map(SM_edge_weight_map const &p)
Definition: sparsematrix_boost.h:433
value_type operator[](X const &x) const
Definition: sparsematrix_boost.h:441
T edge_weight_type
Definition: sparsematrix_boost.h:426
M const & _g
Definition: sparsematrix_boost.h:450
readable_property_map_tag category
Definition: sparsematrix_boost.h:428
Definition: sparsematrix_boost.h:152
SM_edge(SM_edge &&)=default
bool operator!=(const SM_edge &other) const
Definition: sparsematrix_boost.h:181
int target() const
Definition: sparsematrix_boost.h:169
SM_edge()
Definition: sparsematrix_boost.h:158
SM_edge & operator=(SM_edge const &)=default
SM_edge & operator=(SM_edge &&)=default
T _value
Definition: sparsematrix_boost.h:188
int _target
Definition: sparsematrix_boost.h:187
SM_edge(SM_edge const &)=default
int source() const
Definition: sparsematrix_boost.h:166
bool operator==(const SM_edge &other) const
Definition: sparsematrix_boost.h:178
SM_edge(int s, int t, T const &v)
Definition: sparsematrix_boost.h:160
T const & value(X const &) const
Definition: sparsematrix_boost.h:173
int _source
Definition: sparsematrix_boost.h:186
Definition: sparsematrix_boost.h:211
friend class iterator_core_access
Definition: sparsematrix_boost.h:305
reference dereference() const
Definition: sparsematrix_boost.h:264
void decrement()
Definition: sparsematrix_boost.h:278
SM_adjacency_iterator< T > value_type
Definition: sparsematrix_boost.h:221
ug::SparseMatrix< T > M
Definition: sparsematrix_boost.h:220
SM_out_edge_iterator & operator=(SM_out_edge_iterator const &other)=default
intmax_t difference_type
Definition: sparsematrix_boost.h:222
SM_out_edge_iterator(SM_out_edge_iterator const &p)
Definition: sparsematrix_boost.h:235
bool equal(SM_out_edge_iterator const &other) const
Definition: sparsematrix_boost.h:271
SM_out_edge_iterator & operator++()
Definition: sparsematrix_boost.h:286
value_type _base
Definition: sparsematrix_boost.h:303
bool operator==(const SM_out_edge_iterator &other) const
Definition: sparsematrix_boost.h:295
~SM_out_edge_iterator()
Definition: sparsematrix_boost.h:242
iterator_facade< SM_out_edge_iterator< T, out >, SM_adjacency_iterator< T >, std::input_iterator_tag, SM_edge< T >, std::intmax_t > base_class
Definition: sparsematrix_boost.h:219
void increment()
Definition: sparsematrix_boost.h:275
SM_out_edge_iterator()
Definition: sparsematrix_boost.h:227
bool operator!=(const SM_out_edge_iterator &other) const
Definition: sparsematrix_boost.h:298
SM_out_edge_iterator operator++(int)
Definition: sparsematrix_boost.h:290
SM_edge< T > edge_type
Definition: sparsematrix_boost.h:224
SM_edge< T > reference
Definition: sparsematrix_boost.h:223
SM_out_edge_iterator(SM_out_edge_iterator &&p)=delete
SM_out_edge_iterator & operator=(SM_out_edge_iterator &&other)=default
SM_out_edge_iterator(SM_adjacency_iterator< T > w, int src)
Definition: sparsematrix_boost.h:229
int _src
Definition: sparsematrix_boost.h:304
Definition: sparsematrix_boost.h:350
size_t vertex_index_type
Definition: sparsematrix_boost.h:352
vertex_descriptor key_type
Definition: sparsematrix_boost.h:357
vertex_index_type value_type
Definition: sparsematrix_boost.h:355
sparse_matrix_index_map(ug::SparseMatrix< T >const &, boost::vertex_index_t)
Definition: sparsematrix_boost.h:361
vertex_index_type reference
Definition: sparsematrix_boost.h:356
readable_property_map_tag category
Definition: sparsematrix_boost.h:354
size_t vertex_descriptor
Definition: sparsematrix_boost.h:353
sparse_matrix_index_map & operator=(const sparse_matrix_index_map &s)
Definition: sparsematrix_boost.h:370
value_type operator[](T_ x) const
Definition: sparsematrix_boost.h:367
sparse_matrix_index_map(sparse_matrix_index_map const &p)
Definition: sparsematrix_boost.h:359
sparse_matrix_index_map(X const &)
Definition: sparsematrix_boost.h:364
Definition: sparsematrix.h:421
size_t idx() const
Definition: sparsematrix.h:478
size_t index() const
Definition: sparsematrix.h:471
const value_type & value() const
Definition: sparsematrix.h:470
size_t num_rows() const
returns number of rows
Definition: sparsematrix.h:342
row_iterator end_row(size_t r)
Definition: sparsematrix.h:485
size_t num_cols() const
returns the number of cols
Definition: sparsematrix.h:345
row_iterator begin_row(size_t r)
Definition: sparsematrix.h:484
#define untested()
Definition: lua_table_handle.cpp:15
Definition: boost_serialization_routines.h:49
std::pair< typename graph_traits< T >::adjacency_iterator, typename graph_traits< T >::adjacency_iterator > adjacent_vertices(size_t v, ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:108
std::pair< SM_out_edge_iterator< typename T::value_type >, SM_out_edge_iterator< typename T::value_type > > out_edges(size_t v, ug::BidirectionalMatrix< T > const &g)
Definition: bidirectional_boost.h:136
int out_degree(int v, ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:76
std::pair< counting_iterator< size_t >, counting_iterator< size_t > > vertices(ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:60
SM_edge_weight_map< typename T::value_type, ug::BidirectionalMatrix< T > > get(edge_weight_t, ug::BidirectionalMatrix< T > const &g)
Definition: bidirectional_boost.h:157
int num_vertices(ug::BidirectionalMatrix< T > const &M)
Definition: bidirectional_boost.h:70
size_t target(SM_edge< typename T::value_type > const &e, ug::BidirectionalMatrix< T > const &m)
Definition: bidirectional_boost.h:100
size_t source(SM_edge< typename T::value_type > const &e, ug::BidirectionalMatrix< T > const &)
Definition: bidirectional_boost.h:94
the ug namespace
bool iszero(__T __val)
Definition: sparsematrix_impl.h:53
AlphaMatVec_X_Expression< L, operation_sub, R > operator-(const TE_AMV_X< L > &l, const TE_AMV_X< R > &r)
create AlphaMatVec_X_Expression<L, operation_minus, R> by conjunction of TE_AMV_X<L> + TE_AMV_X<R>
Definition: template_expressions.h:215
AlphaMatVec_X_Expression< L, operation_add, R > operator+(const TE_AMV_X< L > &l, const TE_AMV_X< R > &r)
create AlphaMatVec_X_Expression<L, operation_add, R> by conjunction of TE_AMV_X<L> + TE_AMV_X<R>
Definition: template_expressions.h:208
Definition: sparsematrix_boost.h:309
SM_traversal_tag traversal_category
Definition: sparsematrix_boost.h:316
int degree_size_type
Definition: sparsematrix_boost.h:320
disallow_parallel_edge_tag edge_parallel_category
Definition: sparsematrix_boost.h:315
SM_adjacency_iterator< T > adjacency_iterator
Definition: sparsematrix_boost.h:319
int vertices_size_type
Definition: sparsematrix_boost.h:321
counting_iterator< size_t > vertex_iterator
Definition: sparsematrix_boost.h:317
int vertex_descriptor
Definition: sparsematrix_boost.h:312
SM_edge< T > edge_descriptor
Definition: sparsematrix_boost.h:313
directed_tag directed_category
Definition: sparsematrix_boost.h:314
SM_out_edge_iterator< T > out_edge_iterator
Definition: sparsematrix_boost.h:318
sparse_matrix_index_map< T > type
Definition: sparsematrix_boost.h:377
type const_type
Definition: sparsematrix_boost.h:378
#define incomplete()
Definition: trace.h:10
function ProblemDisc new(problemDesc, dom)