C++ 操作员+;在稀疏矩阵中:I不';我没有发现任何错误

C++ 操作员+;在稀疏矩阵中:I不';我没有发现任何错误,c++,matrix,sparse-matrix,matrix-storage,C++,Matrix,Sparse Matrix,Matrix Storage,大家好,我实现了一个稀疏矩阵,存储在修改过的压缩稀疏行中!构造函数工作得很好,我可以验证它,但是操作符+有一个奇怪的行为:如果我有一个非零值,那么和不能计算正确的结果。 描述了一种改进的压缩稀疏行方法 我的最小工作代码如下: # include <initializer_list> # include <vector> # include <iosfwd> # include <string> # include <cstdlib> #

大家好,我实现了一个稀疏矩阵,存储在修改过的压缩稀疏行中!构造函数工作得很好,我可以验证它,但是操作符+有一个奇怪的行为:如果我有一个非零值,那么和不能计算正确的结果。 描述了一种改进的压缩稀疏行方法 我的最小工作代码如下:

# include <initializer_list>
# include <vector>
# include <iosfwd>
# include <string>
# include <cstdlib>
# include <cassert>
# include <iomanip>
# include <cmath>
# include <set>
# include <fstream>
# include <algorithm>
# include <exception>

template <typename data_type>
class MCSRmatrix;             

template <typename T>
std::ostream& operator<<(std::ostream& os ,const MCSRmatrix<T>& m) noexcept ;


template <typename T>
MCSRmatrix<T> operator+(const MCSRmatrix<T>& m1, const MCSRmatrix<T>& m2 ) ;

template <typename data_type>
class MCSRmatrix {

   public:
      using itype = std::size_t ;

      template <typename T>
      friend std::ostream& operator<<(std::ostream& os ,const MCSRmatrix<T>& m) noexcept ;

      template <typename T>
      friend MCSRmatrix<T> operator+(const MCSRmatrix<T>& m1, const MCSRmatrix<T>& m2 ) ;

   public: 

      constexpr MCSRmatrix( std::initializer_list<std::initializer_list<data_type>> rows);

      constexpr MCSRmatrix(const std::size_t& ) noexcept; 

      const data_type& operator()(const itype r , const itype c) const noexcept ;

      data_type operator()(const itype r , const itype c) noexcept ;

      auto constexpr printMCSR() const noexcept ;

   private:

     std::vector<data_type> aa_ ;    // vector of value 
     std::vector<itype>     ja_ ;    // pointer vector 

     int dim ; 

     std::size_t constexpr findIndex(const itype row ,  const itype col) const noexcept ;
};

template <typename T>
constexpr MCSRmatrix<T>::MCSRmatrix( std::initializer_list<std::initializer_list<T>> rows)
{
      this->dim  = rows.size();
      auto _rows = *(rows.begin());

      aa_.resize(dim+1);
      ja_.resize(dim+1);

      if(dim != _rows.size())
      {
          throw std::runtime_error("Error in costructor! MCSR format require square matrix!");  
      }

      itype w = 0 ;
      ja_.at(w) = dim+2 ;
      for(auto ii = rows.begin(), i=1; ii != rows.end() ; ++ii, i++)
      {
          for(auto ij = ii->begin(), j=1, elemCount = 0 ; ij != ii->end() ; ++ij, j++ )   
          {
              if(i==j)
                 aa_[i-1] = *ij ;
              else if( i != j && *ij != 0 )
              {   
                 ja_.push_back(j); 
                 aa_.push_back(*ij); 
                 elemCount++ ;
              }
              ja_[i] = ja_[i-1] + elemCount;           
          }
      }     
      printMCSR();
}





template <typename T>
constexpr MCSRmatrix<T>::MCSRmatrix(const std::size_t& n ) noexcept
{
         this->dim = n;
         aa_.resize(dim+1); 
         ja_.resize(dim+1);

      for(std::size_t i = 0; i < aa_.size()-1 ; i++)
        aa_.at(i) = 1 ;    

      for(std::size_t i = 0; i < ja_.size() ; i++)
        ja_.at(i) = aa_.size()+1 ;   


}     


template <typename T>
std::size_t constexpr MCSRmatrix<T>::findIndex(const itype row ,  const itype col) const noexcept 
{    
     assert( row > 0 && row <= dim && col > 0 && col <= dim ); 
     if(row == col)
     {
       return row-1;
     }
     int i = -1;

      for(int i = ja_.at(row-1)-1 ; i < ja_.at(row)-1 ; i++ )
      {
            if( ja_.at(i) == col ) 
            { 
              return i ;
            }
      }
      return -1;
}


template <typename T>
inline auto constexpr MCSRmatrix<T>::printMCSR() const noexcept 
{
      for(auto& x : aa_ )
          std::cout << x << ' ' ;
      std::cout << std::endl;

      for(auto& x : ja_ )
          std::cout << x << ' ' ;
      std::cout << std::endl;
}

template <typename T>
const T& MCSRmatrix<T>::operator()(const itype r , const itype c) const noexcept 
{     
     auto i = findIndex(r,c); 
     if( i != -1 && i < aa_.size() )
     {      
            return aa_.at(i) ;
     }
     else
     {
            return aa_.at(dim) ;
     }       
}


template <typename T>
T MCSRmatrix<T>::operator()(const itype r , const itype c) noexcept 
{     
     auto i = findIndex(r,c); 
     if( i != -1 && i < aa_.size() )
     {      
            return aa_.at(i) ;
     }
     else
     {
            return aa_.at(dim) ;
     }       
}

// non member operator

template <typename T>
std::ostream& operator<<(std::ostream& os ,const MCSRmatrix<T>& m) noexcept 
{
     for(std::size_t i=1 ; i <= m.dim ; i++ )
     {       
         for(std::size_t j=1 ; j <= m.dim ; j++)   
            os << std::setw(8) << m(i,j) << ' ' ;
         os << std::endl;   
     } 
     return os;
}


// perform sum by 2 Mod Comp Sparse Row matrices 
template <typename T>
MCSRmatrix<T> operator+(const MCSRmatrix<T>& m1, const MCSRmatrix<T>& m2 )
{
      if(m1.dim != m2.dim)
      {
          throw std::runtime_error("Matrixs dimension does not match! Error in operator +");  
      }
      else
      {
         MCSRmatrix<T> res(m1.dim);



         for(auto i=0; i < res.dim ; i++)
            res.aa_.at(i) = m1.aa_.at(i)  + m2.aa_.at(i) ; 

         res.ja_.at(0) = res.dim+2;

         std::set<unsigned int> ctrl; 


         int n1=0, n2=0, j1=0 , j2 =0;
         for(auto i=0 ; i < res.dim  ; i++)
         {

           ctrl.clear();

           n1 = m1.ja_.at(i+1)- m1.ja_.at(i) ;
           n2 = m2.ja_.at(i+1)- m2.ja_.at(i) ;


           j1=0 , j2=0 ;

           auto sum1 = 0. , sum2 = 0. , sum=0.;


            for(auto j = 0; j < std::max(n1,n2) ; j++ )
            {
               if(n1 && n2) 
               {
                 if(m1.ja_.at(m1.ja_.at(i)-1 + j1 ) == m2.ja_.at(m2.ja_.at(i)-1 + j2)) 
                 {
                     ctrl.insert(m1.ja_.at(m1.ja_.at(i)-1 + j1 ));

                     sum = m1.aa_.at(m1.ja_.at(i)-1 + j1 ) + m2.aa_.at(m2.ja_.at(i)-1 + j2) ;


                 }
                 else if(m1.ja_.at(m1.dim+1 + j1 ) != m2.ja_.at(m2.dim+1 + j2))
                 {   
                     ctrl.insert(m1.ja_.at(m1.ja_.at(i)-1 + j1 ));
                     ctrl.insert(m2.ja_.at(m1.ja_.at(i)-1 + j2 ));

                     sum1 = m1.aa_.at(m1.ja_.at(i)-1 + j1);               
                     sum2 = m2.aa_.at(m2.ja_.at(i)-1 + j1);     
                 }
               }        
               else if(n1)
               {  
                  ctrl.insert(m1.ja_.at(m1.ja_.at(i)-1 + j1 ));
                  sum1 = m1.aa_.at(m1.ja_.at(i)-1 + j1);               
               }
               else if(n2)
               {
                  ctrl.insert(m2.ja_.at(m2.ja_.at(i)-1 + j2 ));
                  sum2 = m2.aa_.at(m2.ja_.at(i)-1 + j2);     
               }
               if(sum1)
               {
                  res.aa_.push_back(sum1);
                  res.ja_.push_back(m1.ja_.at(m1.ja_.at(i)-1 + j1)) ;
               }
               if(sum2)
               {
                  res.aa_.push_back(sum2);
                  res.ja_.push_back(m2.ja_.at(m2.ja_.at(i)-1 + j2 ));
               }
               if(sum)
               {    

                    res.aa_.push_back(sum);
                    res.ja_.push_back(m1.ja_.at(m1.ja_.at(i)-1 + j1 ));
               }

               if(j1 < n1) j1++ ;
               if(j2 < n2) j2++ ;
             } 


            res.ja_.at(i+1) = res.ja_.at(i) + ctrl.size() ;  

         }
         return res ;   
      }
}
但是如果我在
m01
矩阵中更改元素
(3,2)
的值。。 因此矩阵变成:

 MCSRmatrix<int> m01 =  {{0,1,0,0},{0,3,0,0},{0,2,0,3},{0,0,0,1}};
但看看向量(第一个
矩阵.dim
是对角线元素的值向量,后面的元素是非对角线非零元素,看起来矩阵与此结果不同) 它们是:

aa_ = 1 25 33 45 0 2 2 14 2 3 3 1 1 
ja_ = 6 8 9 10 11 2 2 4 2 4 4 3 3 
另一个例子是,如果我将这一行插入到主目录中:

 MCSRmatrix<double> m3  = {{1.01, 0 , 0,0}, {0, 4.07, 0,0},{0,0,6.08,0},{1.06,0,2.2,9.9} };   

  MCSRmatrix<double> m4  = {{ 1.21, 0 , 1.06,0 }, {0, 3.31, 1.06,0},{0,1.06,-6.01,0},{4.12,0,1.06,-8.3}}; 

  MCSRmatrix<double> m5 = m3+m4 ;  

  cout << m5 ;
如果我对m1和m2进行一点更改:

 MCSRmatrix<double> m6  = {{1.01, 0 , 0,0}, {0, 4.07, 0,0},{0,0,6.08,0},{1.06,0,2.2,9.9} }; 
MCSRmatrix<double> m7  = {{ 1.21, 0 , 0,2.15 }, {0, 3.31, 1.03,0},{0,1.06,-6.01,1.01},{4.12,1.1,1.06,-8.3}};
cout << m6+m7 ;
MCSRmatrix m6={{1.01,0,0,0},{0,4.07,0,0},{0,0,6.08,0},{1.06,0,2.2,9};
MCSRM矩阵m7={1.21,0,0,2.15},{0,3.31,1.03,0},{0,1.06,-6.01,1.01},{4.12,1.1,1.06,-8.3};

cout在add循环中设置
sum1
sum2
的部分,您不想同时执行这两个操作,只想执行索引值较低的操作。这是因为较高的列号可能在另一个矩阵中,但在行中更远


另外,
sum2
的索引计算应该使用
j2
而不是
j1
在add循环中设置
sum1
sum2
的部分,您不想同时使用这两种方法,只想使用索引值较低的方法。这是因为较高的列号可能在另一个矩阵中,但在行中更远


另外,
sum2
的指数计算应该使用
j2
而不是
j1

谢谢回复。。你能解释清楚吗?如何选择较低的索引值,从而选择sum1或sum2必须使用的索引?我已经在sum2的计算中更改了索引(但没有更改)。在
else中,如果(m1.ja_u2;at(m1.dim+1+j1)!=m2.ja_2;at(m2.dim+1+j2))
我必须执行2和,那么事实是
m1.ja_2;at(m1.dim+1+j1)!=m2.ja_uux.at(m2.dim+1+j2)
表示如果在
m1.aa_ux1]
中存在一个非零,它不同于
m2.aa_ux2]
,因此这两个分量对向量
res.aa_x2
有两个贡献,谢谢回答。。你能解释清楚吗?如何选择较低的索引值,从而选择sum1或sum2必须使用的索引?我已经在sum2的计算中更改了索引(但没有更改)。在
else中,如果(m1.ja_u2;at(m1.dim+1+j1)!=m2.ja_2;at(m2.dim+1+j2))
我必须执行2和,那么事实是
m1.ja_2;at(m1.dim+1+j1)!=m2.ja_uu.at(m2.dim+1+j2)
表示如果在
m1.aa[index1]
中存在一个与
m2.aa[index2]
不同的非零,那么这两个分量对向量
res.aa\ucode>有两个贡献
aa_ = 1 25 33 45 0 2 2 14 2 3 3 1 1 
ja_ = 6 8 9 10 11 2 2 4 2 4 4 3 3 
 MCSRmatrix<double> m3  = {{1.01, 0 , 0,0}, {0, 4.07, 0,0},{0,0,6.08,0},{1.06,0,2.2,9.9} };   

  MCSRmatrix<double> m4  = {{ 1.21, 0 , 1.06,0 }, {0, 3.31, 1.06,0},{0,1.06,-6.01,0},{4.12,0,1.06,-8.3}}; 

  MCSRmatrix<double> m5 = m3+m4 ;  

  cout << m5 ;
    2.22        0     1.06        0 
       0     7.38     1.06        0 
       0     1.06     0.07        0 
    5.18        0     3.26      1.6 
 MCSRmatrix<double> m6  = {{1.01, 0 , 0,0}, {0, 4.07, 0,0},{0,0,6.08,0},{1.06,0,2.2,9.9} }; 
MCSRmatrix<double> m7  = {{ 1.21, 0 , 0,2.15 }, {0, 3.31, 1.03,0},{0,1.06,-6.01,1.01},{4.12,1.1,1.06,-8.3}};
cout << m6+m7 ;