SciPy: Симметричная перестановка разреженной матрицы CSR - PullRequest
0 голосов
/ 18 марта 2019

Я хотел бы симметрично переставить разреженную матрицу, переставляя строки и столбцы таким же образом. Например, я хотел бы повернуть строки и столбцы, что занимает:

 1     2     3
 0     1     0
 0     0     1

до

 1     0     0
 0     1     0
 2     3     1

В Octave или MATLAB это можно сделать кратко с помощью матричной индексации:

A = sparse([1 2 3; 0 1 0; 0 0 1]);
perm = [2 3 1];
Aperm = A(perm,perm);

Я заинтересован в том, чтобы сделать это на Python с NumPy / SciPy. Вот попытка:

#!/usr/bin/env python
import numpy as np
from scipy.sparse import csr_matrix

row = np.array([0, 0, 0, 1, 2])
col = np.array([0, 1, 2, 1, 2])
data = np.array([1, 2, 3, 1, 1])
A = csr_matrix((data, (row, col)), shape=(3, 3))

p = np.array([1, 2, 0])

#Aperm = A[p,p]            # gives [1,1,1], the permuted diagonal
Aperm = A[:,p][p,:]        # works, but more verbose

Есть ли более чистый способ для выполнения такого рода симметричной перестановки матрицы?

(меня больше интересует краткий синтаксис, чем производительность)

1 Ответ

3 голосов
/ 18 марта 2019

В MATLAB

A(perm,perm)

является блочной операцией. В numpy A[perm,perm] выделяются элементы по диагонали.

A[perm[:,None], perm]

- блок индексации. Для диагонали MATLAB требуется что-то вроде sub2ind. То, что сжато в одном, более многословно в другом, и v.v.

На самом деле numpy использует одну и ту же логику в обоих случаях. Он «транслирует» один индекс против другого, A (n,) против (n,) в диагональном регистре и (n,1) против (1,n) в блочном регистре. Результаты имеют форму (n,) и (n,n).

Это индексирование numpy работает и с разреженными матрицами, хотя и не так быстро. Он фактически использует матричное умножение для такого рода индексации - с помощью матрицы «экстрактора», основанной на индексах (возможно, 2, M*A*M.T).


Документация MATLAB о матрице перестановок:

https://www.mathworks.com/help/matlab/math/sparse-matrix-operations.html#f6-13070

...