Je serais heureux de suggérer une implémentation (peut-être évidente) de ceci, qui pourrait être faite en Python pur ou en C/Cython si vous avez le temps et l'espace pour de nouvelles dépendances, et si vous avez besoin que ce soit plus rapide.
Une matrice éparse en N dimensions peut supposer que la plupart des éléments sont vides, nous utilisons donc un dictionnaire avec des clés sur les tuples :
class NDSparseMatrix:
def __init__(self):
self.elements = {}
def addValue(self, tuple, value):
self.elements[tuple] = value
def readValue(self, tuple):
try:
value = self.elements[tuple]
except KeyError:
# could also be 0.0 if using floats...
value = 0
return value
et vous l'utiliserez comme ça :
sparse = NDSparseMatrix()
sparse.addValue((1,2,3), 15.7)
should_be_zero = sparse.readValue((1,5,13))
Vous pourriez rendre cette implémentation plus robuste en vérifiant que l'entrée est en fait un tuple, et qu'elle ne contient que des entiers, mais cela ne fera que ralentir les choses, donc je ne m'en préoccuperais pas à moins que vous ne diffusiez votre code au monde entier plus tard.
EDIT - une implémentation Cython du problème de multiplication de matrice, en supposant que l'autre tenseur est un tableau NumPy à N dimensions ( numpy.ndarray
) pourrait ressembler à ceci :
#cython: boundscheck=False
#cython: wraparound=False
cimport numpy as np
def sparse_mult(object sparse, np.ndarray[double, ndim=3] u):
cdef unsigned int i, j, k
out = np.ndarray(shape=(u.shape[0],u.shape[1],u.shape[2]), dtype=double)
for i in xrange(1,u.shape[0]-1):
for j in xrange(1, u.shape[1]-1):
for k in xrange(1, u.shape[2]-1):
# note, here you must define your own rank-3 multiplication rule, which
# is, in general, nontrivial, especially if LxMxN tensor...
# loop over a dummy variable (or two) and perform some summation:
out[i,j,k] = u[i,j,k] * sparse((i,j,k))
return out
Bien que vous aurez toujours besoin de le faire à la main pour le problème en question, parce que (comme mentionné dans le commentaire du code) vous aurez besoin de définir quels indices vous additionnez, et faites attention aux longueurs des tableaux ou les choses ne fonctionneront pas !
EDIT 2 - si l'autre matrice est également éparse, alors vous n'avez pas besoin de faire la boucle à trois voies :
def sparse_mult(sparse, other_sparse):
out = NDSparseMatrix()
for key, value in sparse.elements.items():
i, j, k = key
# note, here you must define your own rank-3 multiplication rule, which
# is, in general, nontrivial, especially if LxMxN tensor...
# loop over a dummy variable (or two) and perform some summation
# (example indices shown):
out.addValue(key) = out.readValue(key) +
other_sparse.readValue((i,j,k+1)) * sparse((i-3,j,k))
return out
Ma suggestion pour une implémentation en C serait d'utiliser un simple struct pour contenir les indices et les valeurs :
typedef struct {
int index[3];
float value;
} entry_t;
vous aurez alors besoin de fonctions pour allouer et maintenir un tableau dynamique de ces structs, et les rechercher aussi vite que nécessaire ; mais vous devriez tester l'implémentation Python en place pour les performances avant de vous préoccuper de ce genre de choses.
0 votes
Cet article pourrait vous aider stackoverflow.com/questions/4490961/
0 votes
...mais pas épars, malheureusement.
0 votes
Qu'entendez-vous par "matrice en 2D" ? Si vous voulez dire une matrice représentant une transformation linéaire en 2D, alors vous parlez d'une matrice 2x2 de valeurs réelles (approximées par des valeurs à virgule flottante) avec un déterminant 1 pour une rotation rigide. Si vous voulez également représenter la translation, vous intégrez la matrice 2x2 dans une matrice 3x3, et si vous voulez permettre le cisaillement ou l'expansion/contraction, vous pouvez relâcher l'exigence du déterminant - mais même dans ce cas, cela représente un total de 9 valeurs à virgule flottante. Pourquoi voulez-vous/avez-vous besoin d'une représentation éparse ?
0 votes
@Peter "une matrice en 2D" signifie une matrice en 2 dimensions. Une unité dans une matrice en 2D peut être représentée par (x,y, r), où x et y sont les coordonnées et r est la valeur stockée en (x, y). J'ai besoin d'une représentation clairsemée parce que lorsque x & y sont très très grands, disons x<10^5, y < 10^4, ET seulement très peu de données sont stockées dans la matrice, disons 10^4. numpy fournit une matrice clairsemée pour la matrice 2d. Mais très souvent, nous avons besoin de 3d ou même n-d. Je pense que le cas n-d est trop général. Donc toute solution pour 3d est bonne pour moi.
0 votes
Merci - J'étais confus par le P.S. dans votre question (il m'a semblé que vous vouliez multiplier un tas de tuples euclidiens par une matrice, style algèbre linéaire). Mais si vous parlez de matrices m x n x o, alors il semble que votre implémentation "clairsemée" va devoir fournir une sorte d'interface d'itérateur afin que vous puissiez implémenter la multiplication (élément par élément).