Numpy“智能"对称矩阵 [英] Numpy ‘smart’ symmetric matrix

查看:22
本文介绍了Numpy“智能"对称矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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())

这在合理的假设下有效(例如在运行 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, index, value): (i, j) = 索引...

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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆