Numpy "intelligent" de la matrice symétrique
Est-il intelligent et économe en espace symétrique de la matrice dans numpy qui automatiquement et de manière transparente) remplit la position à [j][i]
quand [i][j]
est écrit?
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
Automatique Hermitian serait bien aussi, bien que je ne vais pas besoin de cela au moment de la rédaction.
- Vous pourriez envisager de marquer la réponse acceptée, si cela résout votre problème. 🙂
- Je voulais attendre une meilleure (c'est à dire intégré et efficace de la mémoire) réponse à venir. Il n'y a rien de mal avec votre réponse, bien sûr, donc je vais l'accepter de toute façon.
Vous devez vous connecter pour publier un commentaire.
Si vous pouvez vous permettre de symétriser la matrice juste avant de faire les calculs, les éléments suivants doivent être raisonnablement rapide:
Cela fonctionne sous des hypothèses raisonnables (par exemple ne pas faire les deux
a[0, 1] = 42
et contradictoiresa[1, 0] = 123
avant d'exécutersymmetrize
).Si vous avez vraiment besoin d'un transparent symétrisation, vous pourriez envisager de sous-classement numpy.ndarray et simplement redéfinir
__setitem__
:(ou l'équivalent avec des matrices au lieu des tableaux, selon vos besoins). Cette approche prend même en charge plus compliqué affectations, comme
a[:, 1] = -1
, qui définit correctementa[1, :]
éléments.Noter que Python 3 suppression de la possibilité de l'écriture
def …(…, (i, j),…)
, de sorte que le code doit être légèrement adapté avant d'exécuter avec Python 3:def __setitem__(self, indexes, value): (i, j) = indexes
...__getitem__(self, (i, j))
échoue lorsque l'on fait un simpleprint
sur une sous-classe de l'instance de array. La raison en est queprint
appels__getitem__()
avec un index entier, de sorte que plus de travail est nécessaire, même pour un simpleprint
. La solution avec__setitem__()
fonctionne avecprint
(évidemment), mais souffre d'un problème similaire:a[0] = [1, 2, 3]
ne fonctionne pas, pour la même raison (ce n'est pas une solution parfaite). Un__setitem__()
solution a l'avantage d'être plus robuste, depuis le bloc mémoire est correcte. Pas trop mauvais. 🙂La question plus générale de traitement optimal des matrices symétriques dans numpy m'énerve trop.
Après recherche, je pense que la réponse est probablement que numpy est quelque peu limitée par la disposition de la mémoire supportd par le sous-jacent BLAS routines pour les matrices symétriques.
Alors que certaines routines BLAS faire exploiter la symétrie pour accélérer les calculs sur des matrices symétriques, ils utilisent toujours la même structure de la mémoire comme une matrice, qui est,
n^2
l'espace plutôt que den(n+1)/2
. Ils dit que la matrice est symétrique et de n'utiliser que les valeurs soit dans le haut ou le bas du triangle.Certains
scipy.linalg
routines de faire accepter les drapeaux (commesym_pos=True
surlinalg.solve
) qui sont répercutés sur les routines BLAS, bien que plus de soutien pour de cette dans numpy serait sympa, en particulier des wrappers pour des routines comme DSYRK (symétrique de rang k de mise à jour), ce qui permettrait à un Gramme de la matrice calculé un peu juste plus rapide que la dot(M. T, M).(Peut sembler pinailleurs à vous soucier de l'optimisation pour un 2x facteur constant sur le temps et/ou dans l'espace, mais il peut faire une différence à ce seuil de quelle taille vous avez un problème vous pouvez gérer sur une seule machine...)
Il y a un certain nombre de bien-connu des moyens de stockage des matrices symétriques ils n'ont pas besoin d'occuper n^2 éléments de stockage. En outre, il est possible de réécrire les opérations les plus courantes pour accéder à ces révisé le moyen de stockage. L'ouvrage définitif est Golub et Van Loan, Matrice de Calculs, 3ème édition, 1996, Johns Hopkins University Press, articles de 1,27-1.2.9. Par exemple, les citant de la forme (1.2.2), dans une matrice symétrique seulement besoin de stocker
A = [a_{i,j} ]
pouri >= j
. Ensuite, en supposant que le vecteur la tenue de la matrice est notée V, et que A est n-par-n, mettrea_{i,j}
dansCela suppose 1-indexation.
Golub et Van Loan vous proposons un Algorithme 1.2.3 qui vous montre comment accéder à un tel stockées V pour calculer
y = V x + y
.Golub et Van Loan également fournir un moyen de stockage d'une matrice à diagonale dominante formulaire. Ce n'est pas de gagner de la place, mais prend en charge l'accès pour certains autres types d'opérations.
C'est simple, clair python et pas numpy, mais j'ai juste jeté une routine pour remplir
une matrice symétrique (et un programme de test pour s'assurer qu'il est correct):
Il est trivial de Pythonically remplir
[i][j]
si[j][i]
est rempli. Le stockage de la question est un peu plus intéressant. On peut compléter le tableau numpy classe avec unpacked
attribut qui est utile à la fois pour gagner de la place et pour plus tard, lire les données.``