如果你能在进行计算前对矩阵进行对称,下面的计算应该是相当快的。
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
)。
如果你真的需要一个透明的对称性,你可以考虑子类化numpy.ndarray并简单地重新定义__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, :]
元素。
请注意,Python 3删除了编写def …(…, (i, j),…)
的可能性,所以代码在运行Python 3之前必须稍作调整。def __setitem__(self, indexes, value): (i, j) = indexes
...