Количество ненулевых элементов в собственной разреженной матрице после того, как бинарный оператор не меняется

SparseMatrix<int,RowMajor> sm(3,3),sm1;
sm.insert(0,0)=1;
sm.insert(1,1)=1;
sm.insert(2,2)=1;
sm.insert(1,2)=1;
sm.insert(2,1)=1;

SparseMatrix<int,RowMajor> I(3,3);
I.insert(0,0)=1;
I.insert(1,1)=1;
I.insert(2,2)=1;
cout<<"SM matrix \n"<<sm<<endl;
sm1=sm-I;
cout<<"SM1 Matrix"<<sm1<<endl;
cout<<"the number of nonzeros\n"<<sm1.nonZeros()<<endl;

Выход

SM matrix 
Nonzero entries:
(1,0) (_,_) (1,1) (1,2) (1,1) (1,2) 

Outer pointers:
0 2 4  $
Inner non zeros:
1 2 2  $

1 0 0 
0 1 1 
0 1 1 

SM1 MatrixNonzero entries:
(0,0) (0,1) (1,2) (1,1) (0,2) 

Outer pointers:
0 1 3  $

0 0 0 
0 0 1 `
0 1 0 

the number of nonzeros
5

person user3383404    schedule 22.05.2015    source источник
comment
извините, я опечатался .. я хотел напечатать это .. cout‹‹количество ненулевых символов\n‹‹sm1.nonZeros()‹‹endl; вывод все тот же..проблема вот в чем   -  person user3383404    schedule 22.05.2015
comment
Я исправил ваш вопрос для вас сейчас - для дальнейшего использования вы можете нажать на ссылку edit выше, чтобы исправить подобные ошибки.   -  person Paul R    schedule 22.05.2015


Ответы (1)


sm1.nonZeros() не смотрит на значения матрицы, а возвращает размер внутреннего массива, который был выделен для хранения значений:

/** \returns the number of non zero coefficients */
inline Index nonZeros() const
{
  if(m_innerNonZeros)
    return innerNonZeros().sum();
  return static_cast<Index>(m_data.size());
}

Если бы вы посмотрели на этот массив в отладчике или обратились к нему через sm1.valuePtr(), вы бы увидели что-то вроде этого:

sm1.m_data.m_values == {0, 0, 1, 1, 0}

Если бы это была плотная матрица, вы могли бы сделать что-то вроде (m1.array() != 0).count(), но это не работает с разреженным модулем. Обходным путем может быть использование карты следующим образом:

cout<<"the number of nonzeros with comparison: \n"
    << (Eigen::Map<Eigen::VectorXi> (sm1.valuePtr(), sm1.nonZeros()).array() != 0).count()
    << endl;

который на самом деле сравнивает каждое значение с 0 и выводит правильный ответ.

Если вы уверены, что не будете добавлять изменения вновь обнуленных значений, вы можете обрезать разреженная матрица:

sm1.prune(1);
cout<<"the number of pruned nonzeros\n"<<sm1.nonZeros()<<endl;

Сначала удаляются значения ниже порога (в данном случае 1), и массив данных выглядит так:

sm1.m_data.m_values == {1, 1}
person Avi Ginsburg    schedule 25.05.2015