numpy的“智能"对称矩阵 [英] Numpy ‘smart’ symmetric matrix
问题描述
在numpy中是否存在一个智能且节省空间的对称矩阵,当写入[i][j]
时,该矩阵会自动(透明地)填充[j][i]
的位置?
Is there a smart and space-efficient symmetric matrix in numpy which automatically (and transparently) fills the position at [j][i]
when [i][j]
is written to?
import numpy
a = numpy.symmetric((3, 3))
a[0][1] = 1
a[1][0] == a[0][1]
# True
print(a)
# [[0 1 0], [1 0 0], [0 0 0]]
assert numpy.all(a == a.T) # for any symmetric matrix
自动Hermitian也会很好,尽管在撰写本文时我不需要.
An automatic Hermitian would also be nice, although I won’t need that at the time of writing.
推荐答案
如果在进行计算之前就可以对称化矩阵,那么以下操作应该相当快:
If you can afford to symmetrize the matrix just before doing calculations, the following should be reasonably fast:
def symmetrize(a):
"""
Return a symmetrized version of NumPy array a.
Values 0 are replaced by the array value at the symmetric
position (with respect to the diagonal), i.e. if a_ij = 0,
then the returned array a' is such that a'_ij = a_ji.
Diagonal values are left untouched.
a -- square NumPy array, such that a_ij = 0 or a_ji = 0,
for i != j.
"""
return a + a.T - numpy.diag(a.diagonal())
这在合理的假设下有效(例如在运行symmetrize
之前不同时执行a[0, 1] = 42
和矛盾的a[1, 0] = 123
).
This works under reasonable assumptions (such as not doing both a[0, 1] = 42
and the contradictory a[1, 0] = 123
before running symmetrize
).
如果您确实需要透明的对称化,则可以考虑子类化numpy.ndarray并简单地重新定义__setitem__
:
If you really need a transparent symmetrization, you might consider subclassing numpy.ndarray and simply redefining __setitem__
:
class SymNDArray(numpy.ndarray):
"""
NumPy array subclass for symmetric matrices.
A SymNDArray arr is such that doing arr[i,j] = value
automatically does arr[j,i] = value, so that array
updates remain symmetrical.
"""
def __setitem__(self, (i, j), value):
super(SymNDArray, self).__setitem__((i, j), value)
super(SymNDArray, self).__setitem__((j, i), value)
def symarray(input_array):
"""
Return a symmetrized version of the array-like input_array.
The returned array has class SymNDArray. Further assignments to the array
are thus automatically symmetrized.
"""
return symmetrize(numpy.asarray(input_array)).view(SymNDArray)
# Example:
a = symarray(numpy.zeros((3, 3)))
a[0, 1] = 42
print a # a[1, 0] == 42 too!
(或等价的矩阵而不是数组,具体取决于您的需求).这种方法甚至可以处理更复杂的分配,例如a[:, 1] = -1
,可以正确设置a[1, :]
元素.
(or the equivalent with matrices instead of arrays, depending on your needs). This approach even handles more complicated assignments, like a[:, 1] = -1
, which correctly sets a[1, :]
elements.
请注意,Python 3消除了编写def …(…, (i, j),…)
的可能性,因此在使用Python 3运行之前,必须对代码稍作修改:def __setitem__(self, indexes, value): (i, j) = indexes
…
Note that Python 3 removed the possibility of writing def …(…, (i, j),…)
, so the code has to be slightly adapted before running with Python 3: def __setitem__(self, indexes, value): (i, j) = indexes
…
这篇关于numpy的“智能"对称矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!