Il est trivial de remplir de manière pythonique [i][j]
si [j][i]
est rempli. La question du stockage est un peu plus intéressante. On peut augmenter la classe de tableau numpy avec un attribut packed
qui est utile à la fois pour économiser le stockage et pour lire ultérieurement les données.
class Sym(np.ndarray):
# classe wrapper pour le tableau numpy pour les matrices symétriques. Le nouvel attribut peut emballer la matrice pour optimiser le stockage.
# Utilisation :
# Si vous avez une matrice symétrique A comme un tableau numpy de forme (n,n), Sym(A).packed est un tableau numpy de forme (n(n+1)/2,)
# qui est une version compressée de A. Pour le convertir à nouveau, il suffit d'emballer la liste à plat dans Sym(). Notez que Sym(Sym(A).packed)
def __new__(cls, input_array):
obj = np.asarray(input_array).view(cls)
if len(obj.shape) == 1:
l = obj.copy()
p = obj.copy()
m = int((np.sqrt(8 * len(obj) + 1) - 1) / 2)
sqrt_m = np.sqrt(m)
if np.isclose(sqrt_m, np.round(sqrt_m)):
A = np.zeros((m, m))
for i in range(m):
A[i, i:] = l[:(m-i)]
A[i:, i] = l[:(m-i)]
l = l[(m-i):]
obj = np.asarray(A).view(cls)
obj.packed = p
else:
raise ValueError('La longueur d'entrée unidimensionnelle doit être un nombre triangulaire.')
elif len(obj.shape) == 2:
if obj.shape[0] != obj.shape[1]:
raise ValueError('L'entrée bidimensionnelle doit être une matrice carrée.')
packed_out = []
for i in range(obj.shape[0]):
packed_out.append(obj[i, i:])
obj.packed = np.concatenate(packed_out)
else:
raise ValueError('Le tableau d'entrée doit être en 1 ou 2 dimensions.')
retourner obj
def __array_finalize__(self, obj):
if obj is None: return
self.packed = getattr(obj, 'packed', None)
```
1 votes
Vous pouvez envisager de marquer la réponse comme acceptée, si elle résout votre problème. :)
2 votes
J'ai voulu attendre une meilleure (c'est-à-dire intégrée et efficace en mémoire) réponse à venir. Il n'y a rien de mal avec votre réponse, bien sûr, donc je l'accepterai de toute façon.
0 votes
Je pense qu'à ce jour, vous ne pouvez que sous-classer (non merci) ou envelopper numpy, par exemple en enveloppant numpy en modifiant la façon dont vous remplissez la matrice via vos propres fonctions setter, afin d'obtenir une interface qui y ressemble. Je pense que vous pouvez également ajouter des tableaux masqués pour éviter les calculs en double en aval, tant que les tableaux masqués prennent en charge suffisamment de vos scénarios de manipulation de matrice. Rien n'est intégré ni d'une manière génériquement robuste.
0 votes
numpy.all(a == a.T)
ne semble pas fonctionner pour les matrices symétriques avec desnan
s sur la diagonale.