LCOV - code coverage report
Current view: top level - ugbase/lib_algebra/graph_interface - sparsematrix_boost.h (source / functions) Coverage Total Hit
Test: coverage.info Lines: 0.0 % 51 0
Test Date: 2025-09-21 23:31:46 Functions: 0.0 % 24 0

            Line data    Source code
       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"
      17              : #include "lib_algebra/cpu_algebra/sparsematrix.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              :          >{ //
      38              :         typedef ug::SparseMatrix<T> M;
      39              :         typedef typename M::const_row_iterator iter_t;
      40              :         typedef iterator_facade<
      41              :         SM_adjacency_iterator<T>,
      42              :         typename ug::SparseMatrix<T>::const_row_iterator,
      43              :         std::input_iterator_tag,
      44              :         size_t, // <= reference
      45              :         std::intmax_t // difference_type
      46              :          > base_class;
      47              : 
      48              : public:
      49              :         typedef iter_t* value_type;
      50              :         typedef intmax_t difference_type;
      51              :         typedef size_t reference;
      52              : 
      53              : public:
      54            0 :         SM_adjacency_iterator() : base_class(), _base(nullptr), _end(nullptr){
      55              :         }
      56              :         SM_adjacency_iterator(SM_adjacency_iterator&& p) = delete;
      57            0 :         SM_adjacency_iterator(SM_adjacency_iterator const& p)
      58            0 :                 : _base(p._base?(new iter_t(*p._base)) : nullptr)
      59            0 :                 , _end(p._end?(new iter_t(*p._end)) : nullptr){
      60            0 :         }
      61            0 :         SM_adjacency_iterator(value_type p, value_type e) : base_class(){
      62              :                 assert(p);
      63            0 :                 _base = new iter_t(*p);
      64            0 :                 _end = new iter_t(*e);
      65            0 :                 skip_zeroes();
      66            0 :         }
      67            0 :         ~SM_adjacency_iterator() {
      68            0 :                 delete _base;
      69            0 :                 delete _end;
      70              :                 _base = nullptr;
      71              :                 _end = nullptr;
      72            0 :         }
      73              :         SM_adjacency_iterator& operator=(SM_adjacency_iterator&& other) = delete;
      74            0 :         SM_adjacency_iterator& operator=(const SM_adjacency_iterator& other) {
      75            0 :                 if(other._base){
      76            0 :                         delete _base;
      77            0 :                         _base = new iter_t(*other._base);
      78              :                 }else{ untested();
      79            0 :                         _base = nullptr;
      80              :                 }
      81            0 :                 if(other._end){
      82            0 :                         delete _end;
      83            0 :                         _end = new iter_t(*other._end);
      84              :                 }else{ untested();
      85            0 :                         _end = nullptr;
      86              :                 }
      87            0 :                 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              :         }
     102              :         reference dereference() const {
     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            0 :                 return *_base != *other._base;
     115              :         }
     116              : 
     117              : private:
     118              :         // could use boost::filter_iterator, but does not work yet.
     119            0 :         void skip_zeroes(){
     120            0 :                 while((*_base) != (*_end)){
     121            0 :                         if(iszero(_base->value())){
     122              :                                 ++(*_base);
     123              :                         }else{
     124              :                                 break;
     125              :                         }
     126              :                 }
     127            0 :         }
     128              :         bool equal(SM_adjacency_iterator const& other) const { untested();
     129              :                 assert(_base);
     130              :                 assert(other._base);
     131              :                 return *_base == *other._base;
     132              :         }
     133            0 :         void increment() {
     134              :                 assert(_base);
     135              :                 assert(_end);
     136            0 :                 ++(*_base);
     137            0 :                 skip_zeroes();
     138            0 :         }
     139              :         void decrement() { untested();
     140              :                 // incomplete(); // don't use. too complicated.
     141              :                 assert(_base);
     142              :                 --(*_base);
     143              :         }
     144              : 
     145              : private:
     146              :         value_type _base;
     147              :         value_type _end;
     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;
     188              :         T _value;
     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<
     214              :         SM_out_edge_iterator<T, out>,
     215              :         SM_adjacency_iterator<T>,
     216              :         std::input_iterator_tag,
     217              :         SM_edge<T>, // <= reference
     218              :         std::intmax_t // difference_type
     219              :          > base_class;
     220              :         typedef ug::SparseMatrix<T> M;
     221              :         typedef SM_adjacency_iterator<T> value_type;
     222              :         typedef intmax_t difference_type;
     223              :         typedef SM_edge<T> reference;
     224              :         typedef SM_edge<T> edge_type;
     225              : 
     226              : public: // construct
     227            0 :         explicit SM_out_edge_iterator() : base_class() {
     228              :         }
     229            0 :         explicit SM_out_edge_iterator(SM_adjacency_iterator<T> w, int src)
     230            0 :             : base_class(), _base(w), _src(src) {
     231              :                 if(out){
     232              :                 }else{
     233              :                 }
     234              :         }
     235            0 :         /* explicit */ SM_out_edge_iterator(SM_out_edge_iterator const& p)
     236            0 :             : base_class(p), _base(p._base), _src(p._src){
     237              :                 if(out){
     238              :                 }else{
     239              :                 }
     240              :         }
     241              :         SM_out_edge_iterator(SM_out_edge_iterator&& p) = delete; // why?
     242              :         ~SM_out_edge_iterator(){
     243            0 :         }
     244              :         SM_out_edge_iterator& operator=(SM_out_edge_iterator&& other) =  default;
     245            0 :         SM_out_edge_iterator& operator=(SM_out_edge_iterator const& other) = default;
     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              :         }
     258              :         difference_type operator-(SM_out_edge_iterator const& other) const{ untested();
     259              :                 SM_out_edge_iterator ret(*this);
     260              :                 return ret.base.first - other.base.first;
     261              :         }
     262              : #endif
     263              : private:
     264              :         reference dereference() const {
     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:
     286              :         SM_out_edge_iterator& operator++() {
     287              :                 ++_base;
     288            0 :                 return *this;
     289              :         }
     290              :         SM_out_edge_iterator operator++(int) { untested();
     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:
     303              :         value_type _base;
     304              :         int _src;
     305              :         friend class iterator_core_access;
     306              : }; // SM_out_edge_iterator
     307              : 
     308              : struct SM_traversal_tag
     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;
     313              :         typedef SM_edge<T> edge_descriptor;
     314              :         typedef directed_tag directed_category;
     315              :         typedef disallow_parallel_edge_tag edge_parallel_category;
     316              :         typedef SM_traversal_tag traversal_category;
     317              :         typedef counting_iterator<size_t> vertex_iterator;
     318              :         typedef SM_out_edge_iterator<T> out_edge_iterator;
     319              :         typedef SM_adjacency_iterator<T> adjacency_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            0 : 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              : 
     332              :         typename ug::SparseMatrix<T>::const_row_iterator b(M.begin_row(v));
     333              :         typename ug::SparseMatrix<T>::const_row_iterator e(M.end_row(v));
     334              : 
     335            0 :         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>>
     340            0 :                                         out_edges(int v, ug::SparseMatrix<T> const& g)
     341              : {
     342              :         assert(size_t(v)<g.num_rows());
     343              :         typedef SM_out_edge_iterator<T> Iter;
     344            0 :    auto a = adjacent_vertices(v, g);
     345            0 :         return std::make_pair(Iter(a.first, v), Iter(a.second, v));
     346              : }
     347              : 
     348              : template<class T>
     349              : class sparse_matrix_index_map
     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;
     355              :         typedef vertex_index_type value_type;
     356              :         typedef vertex_index_type reference;
     357              :         typedef vertex_descriptor key_type;
     358              : 
     359              :         sparse_matrix_index_map(sparse_matrix_index_map const& p) {
     360              :         }
     361              :         sparse_matrix_index_map(ug::SparseMatrix<T>const&, boost::vertex_index_t) { untested();
     362              :         }
     363              :         template<class X>
     364              :         sparse_matrix_index_map(X const&) {
     365              :         }
     366              :         template <class T_>
     367              :         value_type operator[](T_ x) const {
     368              :                 return x;
     369              :         }
     370              :         sparse_matrix_index_map& operator=(const sparse_matrix_index_map& s) { untested();
     371              :                 return *this;
     372              :         }
     373              : };
     374              : 
     375              : template<class T>
     376              : struct property_map<ug::SparseMatrix<T>, vertex_index_t>{
     377              :         typedef sparse_matrix_index_map<T> type;
     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>
     399              : int num_vertices(ug::SparseMatrix<T> const& M)
     400              : {
     401              :         assert(M.num_rows() == M.num_cols());
     402              :         return M.num_rows();
     403              : }
     404              : 
     405              : template<class T>
     406            0 : int out_degree(int v, ug::SparseMatrix<T> const& M)
     407              : {
     408              :         int c = 0;
     409            0 :         auto i = out_edges(v, M);
     410            0 :         for(; i.first != i.second; ++i.first) {
     411            0 :                 ++c;
     412              :         }
     413            0 :         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>>
     423              : class SM_edge_weight_map :
     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;
     429              :         typedef edge_weight_type value_type;
     430              :         typedef T& reference;
     431              :         typedef vertex_descriptor key_type;
     432              : 
     433              :         SM_edge_weight_map(SM_edge_weight_map const& p) : _g(p._g) { untested();
     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              :         }
     445              :         SM_edge_weight_map& operator=(const SM_edge_weight_map& s) { untested();
     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>
     462              : inline SM_edge_weight_map<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
        

Generated by: LCOV version 2.0-1