Если вы можете позволить себе симметризовать матрицу непосредственно перед выполнением расчетов, следующее должно быть достаточно быстрым:
def symmetrize(a):
return a + a.T - numpy.diag(a.diagonal())
Это работает при разумных допущениях (например, если не выполнить и a[0, 1] = 42
, и противоречивое a[1, 0] = 123
перед запуском symmetrize
).
Если вам действительно нужна прозрачная симметризация, вы можете рассмотреть создание подкласса 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
…