def ttm(self, mat, dims = None, option = None): """ computes the tensor times the given matrix. arrs is a single 2-D matrix/array or a list of those matrices/arrays.""" if(dims == None): dims = range(0,self.ndims()); #Handle when arrs is a list of arrays if(mat.__class__ == list): if(len(mat) == 0): raise ValueError("the given list of arrays is empty!"); (dims,vidx) = tools.tt_dimscheck(dims, self.ndims(), len(mat)); Y = self.ttm(mat[vidx[0]],dims[0],option); for i in range(1, len(dims)): Y = Y.ttm(mat[vidx[i]],dims[i],option); return Y; if(mat.ndim != 2): raise ValueError ("matrix in 2nd armuent must be a matrix!"); if(dims.__class__ == list): if(len(dims) != 1): raise ValueError("Error in number of elements in dims"); else: dims = dims[0]; if(dims < 0 or dims > self.ndims()): raise ValueError ("Dimension N must be between 1 and num of dimensions"); #Compute the product N = self.ndims(); shp = self.shape; order = [] order.extend([dims]); order.extend(range(0,dims)); order.extend(range(dims+1,N)); newdata = self.permute(order).data; newdata = newdata.reshape(shp[dims], tools.prod(shp)/shp[dims]); if(option == None): newdata = numpy.dot(mat, newdata); p = mat.shape[0]; elif(option == 't'): newdata = numpy.dot(mat.transpose(), newdata); p = mat.shape[1]; else: raise ValueError("Unknown option"); newshp = [p]; newshp.extend(tools.getelts(shp,range(0,dims))); newshp.extend(tools.getelts(shp,range(dims+1,N))); Y = tensor(newdata, newshp); Y = Y.ipermute(order); return Y;
def ttv(self, v, dims): """ Tensor times vector Parameters ---------- v - column vector d - dimensions Returns ------- out : Khatri-Rao product as a numpy array """ (dims,vidx) = tools.tt_dimscheck(dims, self.ndims(), len(v)); remdims = numpy.setdiff1d(range(self.ndims()), dims); if self.ndims() > 1: c = self.permute(numpy.concatenate((remdims, dims))).data; n = self.ndims()-1; sz = numpy.array(self.shape)[numpy.concatenate((remdims, dims))] for i in range(len(dims)-1, -1, -1): c = c.reshape(numpy.prod(sz[0:n]), sz[n], order='F') c = numpy.dot(c, v[vidx[i]]); n = n-1; if n > 0: c = tensor.tensor(c, sz[0:n]); else: c = c[0]; return c;
def ttv(self, v, dims): """ Computes the product of this tensor with the column vector along specified dimensions. Parameters ---------- v - column vector d - dimensions to multiply the product Returns ------- out : a sparse tensor if 50% or fewer nonzeros """ (dims, vidx) = tools.tt_dimscheck(dims, self.ndims(), len(v)) remdims = numpy.setdiff1d(range(self.ndims()), dims) newvals = self.vals subs = self.subs # Multiple each value by the appropriate elements of the appropriate vector for n in range(len(dims)): idx = subs[:, dims[n]] # extract indices for dimension n w = v[vidx[n]] # extract nth vector bigw = w[idx] # stretch out the vector newvals = numpy.multiply(newvals.flatten(), bigw) # Case 0: all dimensions specified - return the sum if len(remdims) == 0: c = numpy.sum(newvals) return c # Otherwise figure out the subscripts and accumulate the results newsubs = self.subs[:, remdims] newsiz = numpy.array(self.shape)[remdims] # Case 1: return a vector if len(remdims) == 1: c = tools.accum_np(newsubs, newvals, newsiz[0]) #if numpy.count_nonzero(c) < 0.5*newsiz[0]: # c = sptensor.sptensor(numpy.arange(newsiz[0]).reshape(newsiz[0],1), c.reshape(newsiz[0],1)); #else: c = tensor.tensor(c, newsiz) return c # Case 2: result is a multi-way array c = sptensor.sptensor(newsubs, newvals.reshape(len(newvals), 1), newsiz) # check to see if it's dense if c.nnz() > 0.5 * numpy.prod(c.shape): return c.totensor() return c
def ttv(self, v, dims): """ Computes the product of this tensor with the column vector along specified dimensions. Parameters ---------- v - column vector d - dimensions to multiply the product Returns ------- out : a sparse tensor if 50% or fewer nonzeros """ (dims, vidx) = tools.tt_dimscheck(dims, self.ndims(), len(v)); remdims = numpy.setdiff1d(range(self.ndims()), dims); newvals = self.vals; subs = self.subs; # Multiple each value by the appropriate elements of the appropriate vector for n in range(len(dims)): idx = subs[:, dims[n]]; # extract indices for dimension n w = v[vidx[n]]; # extract nth vector bigw = w[idx]; # stretch out the vector newvals = numpy.multiply(newvals.flatten(), bigw); # Case 0: all dimensions specified - return the sum if len(remdims) == 0: c = numpy.sum(newvals); return c; # Otherwise figure out the subscripts and accumulate the results newsubs = self.subs[:, remdims]; newsiz = numpy.array(self.shape)[remdims]; # Case 1: return a vector if len(remdims) == 1: c = tools.accum_np(newsubs, newvals, newsiz[0]); #if numpy.count_nonzero(c) < 0.5*newsiz[0]: # c = sptensor.sptensor(numpy.arange(newsiz[0]).reshape(newsiz[0],1), c.reshape(newsiz[0],1)); #else: c = tensor.tensor(c, newsiz); return c; # Case 2: result is a multi-way array c = sptensor.sptensor(newsubs, newvals.reshape(len(newvals), 1), newsiz); # check to see if it's dense if c.nnz() > 0.5*numpy.prod(c.shape): return c.totensor(); return c;
def ttv(self, vec, dims=None): if (dims is None): dims = range(0, self.ndims()) if (vec.__class__ == list): if (len(vec) == 0): raise ValueError("the given list of arrays is empty!") (dims, vidx) = tools.tt_dimscheck(dims, self.ndims(), len(vec)) Y = self.ttv(vec[vidx[0]], dims[0]) for i in range(1, len(dims)): Y = Y.ttv(vec[videx[i]], dims[i]) return Y if (vec.ndim != 1): raise ValueError("param in 2nd argment must be a vector") if (dims.__class__ == list): if (len(dims) != 1): raise ValueError("Error in number of elements in dims") else: dims = dims[0] if (dims < 0 or dims > self.ndims()): raise ValueError( "Dimension N must be between 1 and num of dimensions") N = self.ndims() shp = self.shape order = [] order.extend(range(0, dims)) order.extend(range(dims + 1, N)) order.extend([dims]) newdata = self.permute(order).data newdata = newdata.reshape(tools.prod(shp) / shp[dims], shp[dims]) newdata = numpy.dot(newdata, vec) N -= 1 sz = numpy.array(self.shape)[order] newshp = sz[:N] # newshp = [] # newshp.extend(tools.getelts(shp, range(0, dims))) # newshp.extend(tools.getelts(shp, range(dims+1, N))) Y = tensor(newdata, newshp) return Y
def ttm(self, mat, dims=None, option=None, without=False): """ computes the sptensor times the given matrix. arrs is a single 2-D matrix/array or a list of those matrices/arrays.""" if (dims == None): dims = range(0, self.ndims()) #Handle when arrs is a list of arrays if (mat.__class__ == list): if (len(mat) == 0): raise ValueError("the given list of arrays is empty!") (dims, vidx) = tools.tt_dimscheck(dims, self.ndims(), len(mat), exceptdims=without) Y = self.ttm(mat[vidx[0]], dims[0], option) for i in range(1, len(dims)): Y = Y.ttm(mat[vidx[i]], dims[i], option) return Y if (mat.ndim != 2): raise ValueError("matrix in 2nd armuent must be a matrix!") if (option != None): if (option == 't'): mat = mat.transpose() else: raise ValueError("unknown option.") if (dims.__class__ == list): if (len(dims) != 1): raise ValueError("Error in number of elements in dims") else: dims = dims[0] if (dims < 0 or dims > self.ndims()): raise ValueError( "Dimension N must be between 1 and num of dimensions") #Check that sizes match if (self.shape[dims] != mat.shape[1]): raise ValueError("size mismatch on V") #Compute the new size newsiz = list(self.shape) newsiz[dims] = mat.shape[0] #Compute Xn Xnt = sptenmat.sptenmat(self, None, [dims], None, 't') rdims = Xnt.rdims cdims = Xnt.cdims I = [] J = [] for i in range(0, len(Xnt.subs)): I.extend([Xnt.subs[i][0]]) J.extend([Xnt.subs[i][1]]) Z = (sparse.coo_matrix( (Xnt.vals.flatten(), (I, J)), shape=(tools.getelts(Xnt.tsize, Xnt.rdims).prod(), tools.getelts(Xnt.tsize, Xnt.cdims).prod())) * mat.transpose()) Z = tensor.tensor(Z, newsiz).tosptensor() if (Z.nnz() <= 0.5 * numpy.array(newsiz).prod()): Ynt = sptenmat.sptenmat(Z, rdims, cdims) return Ynt.tosptensor() else: Ynt = tenmat.tenmat(Z.totensor(), rdims, cdims) return Ynt.totensor()