Рад предложить (возможно, очевидную) реализацию этого, которая может быть сделана на чистом Python или C / Cython, если у вас есть время и пространство для новых зависимостей, и вам нужно, чтобы это было быстрее.
Разреженная матрица в N измерениях может предполагать, что большинство элементов пустые, поэтому мы используем словарь с ключами для кортежей:
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
, и вы будете использовать его так:
sparse = NDSparseMatrix()
sparse.addValue((1,2,3), 15.7)
should_be_zero = sparse.readValue((1,5,13))
Выможет сделать эту реализацию более надежной, проверив, что входные данные на самом деле являются кортежем и содержат только целые числа, но это только замедлит процесс, поэтому я не буду беспокоиться, если вы не выпустите свой код в мир позже.
EDIT - реализация на Cython задачи умножения матриц, при условии, что другой тензор - это N-мерный массив NumPy (numpy.ndarray
), может выглядеть так:
#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
Хотя вам всегда нужно будет свернуть это вручную для решения проблемы, потому что (как упомянуто в комментарии к коду) вам нужно будет определить, по каким показателям вы суммируете, и быть осторожнымl о длине массива, иначе вещи не будут работать!
РЕДАКТИРОВАТЬ 2 - если другая матрица также разрежена, вам не нужно выполнять трехстороннее циклическое выполнение:
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
Мое предложение для реализации на C состоит в том, чтобы использовать простую структуру для хранения индексов и значений:
typedef struct {
int index[3];
float value;
} entry_t;
Затем вам понадобятся некоторые функции для выделения и поддержки динамическогомассив таких структур, и искать их так быстро, как вам нужно;но вы должны проверить реализацию Python на производительность, прежде чем беспокоиться об этом.