forループの使用を避けて行列を定義する

Nov 27 2020

サイズがXの3D行列Xがありますa x b x c

次のようにMATLABで3D行列Yを作成したいと思います。

X = rand(10, 10, 5);
[a, b, c] = size(X);

for i = 1 : c
    for j = 1 : a
        for k = 1 : b

            if j<a && k<b
            Y(j, k, i) = X(j+1, k, i) + X(j, k+1, i).^4;
        
            else
            Y(j, k, i) = X(a, b, i) + X(a, b, i).^4;
            end

         end
    end
end

多くのforループを使用しないようにするには、どうすればよいですか?言い換えれば、多くのループを使用せずに、上記のコードをより高速に書き直すにはどうすればよいですか?

回答

2 MichaelTr7 Nov 28 2020 at 06:59

配列/行列のインデックス作成

以下に、同等のインデックスをカバーするインデックスと、操作の前のドットで示される要素ごとの操作を使用して、Z配列と同一の配列を作成する部分をスクリプトに追加しました。乗算や除算などの演算は、それぞれ要素ごとに指定できます。足し算と引き算は要素ごとに機能し、ドット必要ありません。また、配列が同じであり、forループとインデックス付けメソッドが同等の結果をもたらすことを確認するためにifステートメントを追加しました。を使用したインデックス作成は、対応する/それぞれのディメンションの最後のインデックスを参照します。Y.*/.*./.end

スニペット:

Y = zeros(a,b,c);
Y(1:end-1,1:end-1,:) = X(2:end,1:end-1,:) + X(1: end-1, 2:end,:).^4;
Y(end,1:end,:) = repmat(X(a,b,:) + X(a,b,:).^4,1,b,1);
Y(1:end,end,:) = repmat(X(a,b,:) + X(a,b,:).^4,a,1,1);

フルスクリプト:メソッドとチェックの両方を含む

X = rand(10, 10, 5);
[a, b, c] = size(X);

%Initialed for alternative result%
Z = zeros(a,b,c);

%Looping method%
for i = 1 : c
    for j = 1 : a
        for k = 1 : b
            if j < a && k < b
            Y(j, k, i) = X(j+1, k, i) + X(j, k+1, i).^4;
            
            else
            Y(j, k, i) =  X(a, b, i) + X(a, b, i).^4;
            end
         end
    end
end

%Indexing and element-wise method%
Z(1:end-1,1:end-1,:) = X(2:end,1:end-1,:) + X(1: end-1, 2:end,:).^4;
Z(end,1:end,:) = repmat(X(a,b,:) + X(a,b,:).^4,1,b,1);
Z(1:end,end,:) = repmat(X(a,b,:) + X(a,b,:).^4,a,1,1);

%Checking if results match%
if(Z == Y)
   fprintf("Matched result\n"); 
end

MATLABR2019bを使用して実行