I'm very new to Mathematica, and struggling to convert one of the codes I'd written in MATLAB. I am trying to program a function for a generalised inner product between two tensors, that is for example:
In this particular case intuitively I would have three "for" loops on a,b,c, and another three "for" loops on variables l,r and t to place them accordingly in the resulting tensor. Obviously I cannot do it like that, I do not know beforehand the order of input tensors, nor the "fold" of my inner product.
I had already written MATLAB code which works around these problems:
function t_out = inner_product(A, B, nfold)
%Outputs array 1xN indicating the number of elements in each dimension.
%The length of this vector corresponds to the number of dimensions N of
%input arrays
dimA = size(A); dimB = size(B);
%Collect the free indicies of inner product. length(out_dim) determines the
%dimension, its contents represent number of elements in each dimension.
out_dim = [dimA(nfold+1:end), dimB(nfold+1:end)];
%Dimensions of free indicies associated to input matricies A and B
eblock_A = length(dimA(nfold+1:end)); eblock_B = length(dimB(nfold+1:end));
%Memory pre-allocation
t_out = zeros(out_dim);
if isempty(out_dim)
t_out = sum(sum(A.*B));
else
for i = 1:numel(t_out)
%Identifies which element is being worked on in an output matrix
out_access = cell(1,numel(out_dim));
[out_access{:}] = ind2sub(size(t_out),i);
%generates accessors for matricies A and B
sum_accg(1:nfold) = {':'};
sum_accA = [sum_accg, out_access{1:eblock_A}];
sum_accB = [sum_accg, out_access{eblock_A+1:end}];
%Element by element multiplications on "n-fold" dimensions and
%their sum
tmp = A(sum_accA{:}).*B(sum_accB{:});
t_out(out_access{:}) = sum(tmp(:));
end
end
end
For those who do not want to read into it, I work around the summation on a,b and c by choosing a portion of tensors A and B that fall under the summation, multiply them element-by-element, and add all the elements of the resulting tensor. I work around the "for" loops needed to place the elements in the resulting tensor by converting between MATLAB's linear and subscript indexing, in one "for" loop.
The issue I have is that Mathematica does not support linear indexing and conversion between the two (none that I know of). Flattening the table is obviously not an option. I had thought I can introduce a variable number of loops by doing something to the effect of:
InnerProduct[tensor1_, tensor2_, nfold_] := (
dim1free = Dimensions[tensor1][[nfold + 1 ;;]];
dim2free = Dimensions[tensor2][[nfold + 1 ;;]];
t2offset = Dimensions[dim1free][[1]];
iterList = {Table[{x[a], dim1free[[a]]}, {a, t2offset}],
Table[{x[a + t2offset], dim2free[[a]]}, {a,
Dimensions[dim2free][[1]]}]};
Table[Total[Times[Extract[tensor1, pos1], Extract[tensor2, pos2]]], iterList]
)
but that didn't end up working out for me either.
Maybe you know a better, more efficient way of solving this problem using internal mathematica functions?
Many thanks!