Wenn Sie es sich leisten können, die Matrix unmittelbar vor den Berechnungen zu symmetrisieren, sollte Folgendes relativ schnell gehen:
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())
Dies funktioniert unter vernünftigen Voraussetzungen (z. B. nicht beides a[0, 1] = 42
und der Widerspruch a[1, 0] = 123
vor dem Ausführen symmetrize
).
Wenn Sie wirklich eine transparente Symmetrisierung benötigen, können Sie die Unterklasse numpy.ndarray in Betracht ziehen und einfach neu definieren __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)
a = symarray(numpy.zeros((3, 3)))
a[0, 1] = 42
print a
(oder das Äquivalent mit Matrizen anstelle von Arrays, je nach Ihren Anforderungen). Dieser Ansatz behandelt sogar kompliziertere Zuweisungen, wie z. B. a[:, 1] = -1
das korrekte Festlegen von a[1, :]
Elementen.
Beachten Sie, dass Python 3 die Möglichkeit des Schreibens entfernt def …(…, (i, j),…)
hat. Daher muss der Code vor der Ausführung mit Python 3 leicht angepasst werden: def __setitem__(self, indexes, value): (i, j) = indexes
…