Есть ли умная и эффективная пространством симметрическая матрица в numpy, который автоматически (и прозрачно) заполняет положение в [j][i]
когда [i][j]
записан в?
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
Автоматическое Эрмитово также было бы хорошо, хотя мне не будет нужно это во время записи.
Если вы можете себе позволить симметризуйте матрицу непосредственно перед выполнением вычислений, следующее должно быть достаточно быстрым:
def symmetrize(a):
return a + a.T - numpy.diag(a.diagonal())
Это работает при разумных предположениях (например, не выполняется одновременно a [0, 1] = 42
и противоречивое a [1, 0] = 123
перед запуском симметризовать
).
Если вам действительно нужна прозрачная симметризация, вы можете рассмотреть возможность создания подкласса numpy.ndarray и просто переопределить __ setitem __
:
class SymNDArray(numpy.ndarray):
def __setitem__(self, (i, j), value):
super(SymNDArray, self).__setitem__((i, j), value)
super(SymNDArray, self).__setitem__((j, i), value)
def symarray(input_array):
"""
Returns a symmetrized version of the array-like input_array.
Further assignments to the array are 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
…