ベクトル化を交えた組み合わせ計算の方法

10 ビュー (過去 30 日間)
Shota Ino
Shota Ino 2023 年 7 月 1 日
編集済み: Akira Agata 2023 年 7 月 7 日
現在、多変数関数について、各変数を1次元の配列として全ての組み合わせを計算しようとしています。
下記にコードを記しましたが、変数が多くなるにつれて計算に膨大な時間がかかってしまうため高速化したいです。
並列処理はfor文を複数使う際には適用できなかったため、ベクトル化をして、for文を減らせないか検討中です。
下記コードでA,B,Cの各配列から3×3×3のD,Eを変数とした3次元を作成し、計算することは可能でしょうか?
syms A B C D E;
A=1:1:5;
B=1:1:5;
C=1:1:5;
D=1:1:5;
E=1:1:5;
Z=A*B*C*D*E;
OUTPUT=zeros(5,5,5,5,5);
for i=1:3
% for j=1:3
% for k=1:3
% for l=1:3
% for m=1:3
% OUTPUT(i,j,k,l,m)=subs(Z,[A B C D E], [A(1,i) B(1,j) C(1,k) D(1,l) E(1,m)]);
% end
% end
% end
% end
% end

採用された回答

Akira Agata
Akira Agata 2023 年 7 月 3 日
ndgrid を使う方法はいかがでしょうか?
たとえば簡単のため A~E をすべて 1:3 とすると、Z は以下のように計算できます。
% A~E すべての組み合わせに対して A*B*...*E を計算
[A, B, C, D, E] = ndgrid(1:3);
Z = A.*B.*C.*D.*E;
% 結果を確認
[A(:), B(:), C(:), D(:), E(:), Z(:)]
ans = 243×6
1 1 1 1 1 1 2 1 1 1 1 2 3 1 1 1 1 3 1 2 1 1 1 2 2 2 1 1 1 4 3 2 1 1 1 6 1 3 1 1 1 3 2 3 1 1 1 6 3 3 1 1 1 9 1 1 2 1 1 2
  6 件のコメント
Shota Ino
Shota Ino 2023 年 7 月 7 日
F行列の出力結果は2次元です。
全ての組み合わせとは、F行列内の変数(上記であれば w, L, C)について取りうる値の組み合わせを全て求めたいと思っています。例えば、w, L, Cがそれぞれ5通りの値を取りうるなら、2次元のF行列の結果が5×5×5=125通り出力されるようなイメージです。
Akira Agata
Akira Agata 2023 年 7 月 7 日
編集済み: Akira Agata 2023 年 7 月 7 日
ご説明ありがとうございます。
簡単のため、w, L, C がそれぞれ 3 通り (1~3) 、合計 3^3 = 27通り出力されるようなケースを想定すると、以下のようになるかと思います (2通りの手法で出力してみました)。
% w, L, C の全パターンを作成
[w, L, C] = ndgrid(1:3);
% 方法1: pagemtimes を使って一気に計算
n = numel(w);
F1 = repmat([1 nan; 0 1], 1, 1, n);
F2 = repmat([1 0; nan 1], 1, 1, n);
F1(1, 2, :) = 1i*w(:).*L(:);
F2(2, 1, :) = 1i*w(:).*C(:);
Fall = pagemtimes(F1, F2); % -> Fall(:,:,k) が k番目の出力F行列
% 方法2: 後で確認しやすいテーブル型変数に整理しながら作成
tData = table(w(:), L(:), C(:), ...
'VariableNames', {'w', 'L', 'C'});
tData.F1 = arrayfun(@(x) [1 x; 0 1], 1i*tData.w.*tData.L, ...
'UniformOutput', false);
tData.F2 = arrayfun(@(x) [1 0; x 1], 1i*tData.w.*tData.C, ...
'UniformOutput', false);
tData.Fall = cellfun(@(x,y) x*y, tData.F1, tData.F2, ...
'UniformOutput', false);
disp(tData) % -> tData.Fall{k} が k番目の出力F行列
w L C F1 F2 Fall _ _ _ ____________ ____________ ____________ 1 1 1 {2×2 double} {2×2 double} {2×2 double} 2 1 1 {2×2 double} {2×2 double} {2×2 double} 3 1 1 {2×2 double} {2×2 double} {2×2 double} 1 2 1 {2×2 double} {2×2 double} {2×2 double} 2 2 1 {2×2 double} {2×2 double} {2×2 double} 3 2 1 {2×2 double} {2×2 double} {2×2 double} 1 3 1 {2×2 double} {2×2 double} {2×2 double} 2 3 1 {2×2 double} {2×2 double} {2×2 double} 3 3 1 {2×2 double} {2×2 double} {2×2 double} 1 1 2 {2×2 double} {2×2 double} {2×2 double} 2 1 2 {2×2 double} {2×2 double} {2×2 double} 3 1 2 {2×2 double} {2×2 double} {2×2 double} 1 2 2 {2×2 double} {2×2 double} {2×2 double} 2 2 2 {2×2 double} {2×2 double} {2×2 double} 3 2 2 {2×2 double} {2×2 double} {2×2 double} 1 3 2 {2×2 double} {2×2 double} {2×2 double} 2 3 2 {2×2 double} {2×2 double} {2×2 double} 3 3 2 {2×2 double} {2×2 double} {2×2 double} 1 1 3 {2×2 double} {2×2 double} {2×2 double} 2 1 3 {2×2 double} {2×2 double} {2×2 double} 3 1 3 {2×2 double} {2×2 double} {2×2 double} 1 2 3 {2×2 double} {2×2 double} {2×2 double} 2 2 3 {2×2 double} {2×2 double} {2×2 double} 3 2 3 {2×2 double} {2×2 double} {2×2 double} 1 3 3 {2×2 double} {2×2 double} {2×2 double} 2 3 3 {2×2 double} {2×2 double} {2×2 double} 3 3 3 {2×2 double} {2×2 double} {2×2 double}

サインインしてコメントする。

その他の回答 (1 件)

sp6038sy
sp6038sy 2023 年 7 月 1 日
変数の組み合わせを事前に計算し行列演算するのはどうでしょうか。
例) 多変数関数 の場合
syms A B Z;
% 多変数関数
Z = A.*B;
% 変数の組み合わせを計算
A = 1:3;
B = 1:3;
[A, B] = ndgrid(A, B)
A = 3×3
1 1 1 2 2 2 3 3 3
B = 3×3
1 2 3 1 2 3 1 2 3
% 多変数関数に代入
out = subs(Z)
out = 
  1 件のコメント
Shota Ino
Shota Ino 2023 年 7 月 3 日
回答ありがとうございます。
ZをA, Bの組み合わせからなる2次元配列にすることができました。ありがとうございました。しかし、C,D,Eの変数についてfor文で組み合わせ計算を実施する際にサイズ違いによるエラーが出てしまいました。
現在解決手段を模索中です

サインインしてコメントする。

カテゴリ

Help Center および File ExchangeCreating and Concatenating Matrices についてさらに検索

製品


リリース

R2023a

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!