2016-10-05 9 views
1

単一の1xNベクター(異なるサイズの)いくつかの行列を折りたたむことは非常に簡単です:単一の1xN行列に(異なるサイズの)いくつかの行列を変換し、再び

vec = [ A(:)', B(:)', C(:)' ]; 

...しかし、どのように他の方法、つまりvecからU、V、Wを回復することはできますか?

私はA、B、Cのサイズを収集できます。

sizes = [ size(A), size(B), size(C) ]; 

を...しかし、私は、リカバリを行うための任意のきれいな方法を参照することはできません。

k=0; 
U = reshape(vec(k+1:k+Ay*Ax), Ay, Ax); k = k+Ay*Ax; 
V = reshape(vec(k+1:k+By*Bx), By, Bx); k = k+By*Bx; 
W = reshape(vec(k+1:k+Cy*Cx), Cy, Cx); k = k+Cy*Cx; 

eeeeeyYUCK!確かにこれ以上のものがなければならないのですか?


EDIT:CST-リンクの質問に応えて、CST-リンク@、私は実際には7つのオブジェクトを持っているので、私は過度に汎用的である必要はありません。しかし私は実際に次の構造を扱っています:

A = ...; B = ...; C = ...; % only 7 mats 
vec = pack(A,B,C); 
ret = f(vec, g); 
A_, B_, C_ = unpack(ret); 

function ret = g(vec) 
    U, V, W = unpack(vec); 
    % fiddle U V W 
    ret = pack(U,V,W); 
end 

...そしてfはg(vec)を呼び出します。

インナーアンパックを実行するために、私は、7つのターゲット寸法を供給する必要があるので、私は、私は、別のparamようにそのデータを送信する必要がありますするつもりだと思います:

A = ...; B = ...; C = ...; % only 7 mats 
vec = pack(A,B,C); sizes = getsizes(A,B,C); 
ret = f(vec, g, sizes); 
A_, B_, C_ = unpack(ret); 

function ret = g(vec, sizes) 
    U, V, W = unpack(vec, sizes); 
    % fiddle U V W 
    ret = pack(U,V,W); 
end 

... unpack関数はまだA、B、Cにアクセスすることができますが、実際にはその変数sizes変数を使いこなすのが賢明ではありません。

+0

一般的な解決法が必要なのか、それとも3つの行列だけが必要ですか? –

+0

@ CST-Link、良い点、私は質問を編集しました。 –

答えて

1

私は(あなたがこのようにきれいに考慮すればIE)これは、あなたの質問に答えるかどうかわからないんだけど、ここでは3つの行列のためのソリューションです:

A = randi(10,3,1); 
B = randi(10,1,4); 
C = randi(10,5,1); 
vec = [ A(:).', B(:).', C(:).' ]; 
sizes = [size(A).', size(B).', size(C).' ]; 

U = zeros(sizes(:,1).'); 
V = zeros(sizes(:,2).'); 
W = zeros(sizes(:,3).'); 
L = prod(sizes); 
U(:) = vec(1:L(1)); 
V(:) = vec(L(1)+(1:L(2)); 
W(:) = vec(sum(L(1:2))+(1:L(3))); 

、それは非常に簡単に一般的な解決策に拡張することができ入力ベクトルと出力ベクトルはセル配列に格納する必要があります。

function PackUnpack 
A = randi(10,3,2); 
B = randi(10,1,4); 
C = randi(10,5,3); 
[vec,sizes] = pack({A,B,C}); 
ret = unpack(vec,sizes); 
end 

function [vec,sizes] = pack(mats) 
sizes = zeros(2,numel(mats)); 
% build the size vector: 
for k = 1:numel(mats) 
    sizes(:,k) = size(mats{k}).'; 
end 
L = prod(sizes); 
vec = zeros(1,sum(L)); 
pos = cumsum([0 L]); 
% flattening all matrices to one vector 
for k = 1:numel(mats) 
    vec((pos(k)+1):pos(k+1)) = mats{k}(:).'; 
end 
end 

function cell_of_mat = unpack(vec,sizes) 
cell_of_mat = cell(size(sizes,2),1); 
sz = cumsum([0 prod(sizes)]); 
% initialize all matrices to correct size and fill with values 
for k = 1:numel(cell_of_mat) 
    cell_of_mat{k} = zeros(sizes(:,k).'); 
    cell_of_mat{k}(:) = vec((sz(k)+1):sz(k+1)); 
end 
end 
+0

@ p-i一般的なケースの編集を見てください。 'arrayfun'の潜在的な表記法で' for'ループを使うのが好きですし、それらも高速です。 – EBH

+0

ありがとう、素敵なコード!私はちょうど '' 'not ''を使うことができるように見えます。他の人に注意して、私は '[P、Q R] = ret {:};'を実行して実際の行列を別個の主題として得ることができます。私はあなたが 'for 'ループが' arrayfun'よりも優れた性能を発揮すると言って驚いています - 私はどこでも、明示的なループは可能な限り避けるべきです。 –

+1

@Pi '.''を使うのがより良い方法です(http://stackoverflow.com/a/25150319/2627163)。' arrayfun'はちょうど[fancy loop]です(http://stackoverflow.com/a/12526940/2627163)、単純なネストされていない 'for'よりも遅くなります。 – EBH

関連する問題