Если Вы готовы попробовать что-то немного различное, существует платформа ICE от ZeroC. Это - открытый исходный код и поддерживается на в значительной степени каждой ОС, о которой можно думать, а также поддержка языка наличия C++, C#, Java, Ruby, Python и PHP. Наконец, очень легко управлять (отображения языка адаптируются для установки естественно каждому языку). Это также быстро и эффективно. Существует даже усеченная версия для устройств.
Вы можете сделать это в одной строке, используя функции NUM2CELL , чтобы разбить матрицу X
на массив ячеек и CELLFUN для работы с ячейками:
Z = cellfun(@(x) x*Y,num2cell(X,[1 2]),'UniformOutput',false);
Результат Z
- это массив ячеек размером 1 на C , где каждая ячейка содержит матрицу A-by-D . Если вы хотите, чтобы Z
было матрицей A-by-D-by-C , вы можете использовать функцию CAT :
Z = cat(3,Z{:});
ПРИМЕЧАНИЕ: Мое старое решение использовало MAT2CELL вместо NUM2CELL , что было не так лаконично:
[A,B,C] = size(X);
Z = cellfun(@(x) x*Y,mat2cell(X,A,B,ones(1,C)),'UniformOutput',false);
Вот однострочное решение (два, если вы хотите разделить на 3-е измерение):
A = 2;
B = 3;
C = 4;
D = 5;
X = rand(A,B,C);
Y = rand(B,D);
%# calculate result in one big matrix
Z = reshape(reshape(permute(X, [2 1 3]), [A B*C]), [B A*C])' * Y;
%'# split into third dimension
Z = permute(reshape(Z',[D A C]),[2 1 3]);
Отсюда теперь: Z (:,:, i)
содержит результат X (:,:, i) * Y
Пояснение:
Вышеупомянутое может сбивать с толку, но идея проста.
Сначала я возьму третье измерение X
и проведу вертикальную конкатенацию по первому размеру:
XX = cat(1, X(:,:,1), X(:,:,2), ..., X(:,:,C))
... сложность заключалась в том, что C
- это переменная, поэтому вы можете Не обобщайте это выражение с помощью cat или vertcat . Затем мы умножаем это на Y
:
ZZ = XX * Y;
Наконец, я разделил его обратно на третье измерение:
Z(:,:,1) = ZZ(1:2, :);
Z(:,:,2) = ZZ(3:4, :);
Z(:,:,3) = ZZ(5:6, :);
Z(:,:,4) = ZZ(7:8, :);
Итак, вы можете видеть, что для этого требуется только одно матричное умножение, но вы должны изменить форму матрица до и после.
Нет. Есть несколько способов, но это всегда происходит в цикле, прямом или косвенном.
Просто чтобы удовлетворить мое любопытство, зачем вам это вообще?
Я бы подумал о рекурсии, но это единственный другой метод без цикла, который вы можете использовать
Вы можете "развернуть" цикл, т.е. последовательно выписать все умножения, которые произойдут в цикле
В качестве личного предпочтения я предпочитаю, чтобы мой код был как можно более кратким и читабельным.
Вот что я бы сделал, хотя это не соответствует вашим «безциклам». требование:
for m = 1:C
Z(:,:,m) = X(:,:,m)*Y;
end
В результате получается матрица A x D x C Z .
И, конечно же, вы всегда можете предварительно выделить Z, чтобы ускорить процесс, используя Z = нули (A, D, C);
.