Eigen SparseMatrix - установить значения строки

Я пишу симуляцию с Eigen, и теперь мне нужно установить список строк моей ColumnMajor SparseMatrix следующим образом:

In row n: 
  for column elements m:
    if m == n set value to one
    else set value to zero

Внутри разреженной матрицы всегда есть элемент с индексом столбца = индексом строки. Я пытался использовать InnerIterator, но это не сработало, так как у меня есть матрица ColumnMajor. Метод обрезки, предложенный в https://stackoverflow.com/a/21006998/3787689, работал, но мне просто нужно временно установите для недиагональных элементов ноль, а сокращение, похоже, фактически удалит их, что замедлит другую часть программы.

Как мне поступить в этом случае?

Заранее спасибо!

EDIT: я забыл уточнить: разреженная матрица уже заполнена значениями.


person dawirstejeck    schedule 13.08.2014    source источник


Ответы (3)


Используйте триплеты для эффективной вставки:

const int N = 5;
const int M = 10;
Eigen::SparseMatrix<double> myMatrix(N,M); // N by M matrix with no coefficient, hence this is the null matrix

std::vector<Eigen::Triplet<double>> triplets;

for (int i=0; i<N; ++i) {
    triplets.push_back({i,i,1.});
}

myMatrix.setFromTriplets(triplets.begin(), triplets.end());
person Bérenger    schedule 13.08.2014
comment
Спасибо за быстрый ответ, но это не помогает в моем случае. Я отредактировал свой вопрос, чтобы прояснить, что в моей матрице уже есть элементы, которые мне нужно сохранить, за исключением некоторых строк. Насколько я понимаю, функция setFromTriplets удаляет все элементы перед добавлением триплетов. - person dawirstejeck; 14.08.2014

Я решил это так: поскольку я хочу придерживаться матрицы ColumnMajor, я делаю локальную версию RowMajor и использую InnerIterator для присвоения значений конкретным строкам. После этого я перезаписываю свою матрицу результатом.

Eigen::SparseMatrix<float, Eigen::RowMajor> rowMatrix;
rowMatrix = colMatrix;
for (uint i = 0; i < rowTable.size(); i++) {
  int rowIndex = rowTable(i);
  for (Eigen::SparseMatrix<float, Eigen::RowMajor>::InnerIterator 
           it(rowMatrix, rowIndex); it; ++it) {
    if (it.row() == it.col())
      it.valueRef() = 1.0f;
    else
      it.valueRef() = 0.0f;
  }
}
colMatrix = rowMatrix;
person dawirstejeck    schedule 15.08.2014

Для новичков самый простой способ обнулить строку/столбец/блок — просто умножить его на 0,0.

Итак, чтобы исправить всю строку так, как вы хотите, достаточно сделать:

A.row(n) *= 0;         //Set entire row to 0
A.coeffRef(n,n) = 1;   //Set diagonal to 1

Таким образом, вам не нужно менять свой код в зависимости от ордеров RowMajor/ColMajor. Эйген сделает всю работу быстро.

Кроме того, если вы действительно заинтересованы в освобождении памяти после установки строки в 0, просто добавьте A.prune(0,0) после того, как вы закончите редактирование всех строк в вашей матрице.

person Rockcat    schedule 07.11.2019