web-dev-qa-db-ja.com

入力引数の数が明示的に知られていない場合の可変数の入力引数を使用した関数呼び出し

変数pthがあります。これは次元1xnのセル配列で、nはユーザー入力です。 pthの各要素はそれ自体がセル配列であり、k=1:nlength(pth{k})は変数です(別の関数の結果)。各要素pth{k}{kk}ここで、k=1:nおよびkk=1:length(pth{k})は、可変長の整数/ノード番号の1Dベクトルです。要約すると、可変数の可変長ベクトルがあり、使用可能な数のセル配列に編成されています。

pth{1}pth{2}{pth{3}などからベクトルをランダムに取得するときに、考えられるすべての交差点を探してみたいと思います。たとえば、ファイル交換には、それを行うように見えるさまざまな関数があります これは または これ 。私が抱えている問題は、この方法で関数を呼び出す必要があることです。

mintersect(v1,v2,v3,...)

そして、一般的なケースではすべての入力を書き込むことはできません。これは、その数が明確にわからないためです(上記のnになります)。理想的には、私はこのようなことをしたいと思います。

mintersect(pth{1}{1},pth{2}{1},pth{3}{1},...,pth{n}{1})
mintersect(pth{1}{1},pth{2}{2},pth{3}{1},...,pth{n}{1})
mintersect(pth{1}{1},pth{2}{3},pth{3}{1},...,pth{n}{1})
etc...
mintersect(pth{1}{1},pth{2}{length(pth{2})},pth{3}{1},...,pth{n}{1})
mintersect(pth{1}{1},pth{2}{1},pth{3}{2},...,pth{n}{1})
etc...

可能なすべての組み合わせを検討し続けますが、これをコードで書くことはできません。これはファイル交換からの function はすべての可能な組み合わせを見つけるための良い方法のように見えますが、可変数の入力を使用した関数呼び出しで同じ問題があります。

allcomb(1:length(pth{1}),1:length(pth{2}),...,1:length(pth{n}))

入力引数の数が可変であるためにすべての入力引数を物理的に指定できない場合、可変数の入力引数を使用してこの関数呼び出しの問題を回避する方法を誰かが知っていますか?これは、MATLABとOctaveに同じように適用されるため、2つのタグになります。各pth{k}ウェルカムからランダムにベクトルを取得するときのすべての可能な組み合わせ/交差を見つける方法に関するその他の提案

EDIT 27/05/20

マッド物理学者の答えのおかげで、私はうまくいく次のものを使うことになりました:

disp('Computing intersections for all possible paths...')
grids = cellfun(@(x) 1:numel(x), pth, 'UniformOutput', false);
idx = cell(1, numel(pth));
[idx{:}] = ndgrid(grids{:});
idx = cellfun(@(x) x(:), idx, 'UniformOutput', false);
idx = cat(2, idx{:});
valid_comb = [];
k = 1;

for ii = idx'
    indices = reshape(num2cell(ii), size(pth));
    selection = cellfun(@(p,k) p{k}, pth, indices, 'UniformOutput', false);
    if my_intersect(selection{:})
       valid_comb = [valid_comb k];
    endif
    k = k+1;
end

私のバージョンも似ていますが、コンマ区切りのリストの代わりにforループを使用しています。

disp('Computing intersections for all possible paths...')
grids = cellfun(@(x) 1:numel(x), pth, 'UniformOutput', false);
idx = cell(1, numel(pth));
[idx{:}] = ndgrid(grids{:});
idx = cellfun(@(x) x(:), idx, 'UniformOutput', false);
idx = cat(2, idx{:});
[n_comb,~] = size(idx);
temp = cell(n_pipes,1);
valid_comb = [];
k = 1;

for k = 1:n_comb
  for kk = 1:n_pipes
    temp{kk} = pth{kk}{idx(k,kk)};
  end
  if my_intersect(temp{:})
    valid_comb = [valid_comb k];
  end
end

どちらの場合でも、valid_combには有効な組み合わせのインデックスがあり、次のようなものを使用して取得できます。

valid_idx = idx(valid_comb(1),:);
for k = 1:n_pipes
  pth{k}{valid_idx(k)} % do something with this
end

いくつかのサンプルデータ(pth4x1であり、pthの4つの要素は2x19x18x1および69x1)で2つのアプローチをベンチマークすると、次の結果が得られました。

>> benchmark

Elapsed time is 51.9075 seconds.
valid_comb =  7112

Elapsed time is 66.6693 seconds.
valid_comb =  7112

したがって、Mad Physicistのアプローチは約15秒速くなりました。

mintersectが何をしたのかも誤解しており、私が望んでいたことではありません。 2つ以上のベクトルに要素が存在しない組み合わせを見つけたかったので、mintersectのバージョンの記述を終了しました。

function valid_comb = my_intersect(varargin)

  % Returns true if a valid combination i.e. no combination of any 2 vectors 
  % have any elements in common

  comb_idx = combnk(1:nargin,2);
  [nr,nc] = size(comb_idx);
  valid_comb = true;
  k = 1;

  % Use a while loop so that as soon as an intersection is found, the execution stops
  while valid_comb && (k<=nr)
    temp = intersect(varargin{comb_idx(k,1)},varargin{comb_idx(k,2)});
    valid_comb = isempty(temp) && valid_comb;
    k = k+1;
  end

end
3
am304

Madphysicistが指摘したように、私はあなたの最初のセルアレイの最初の構造を誤解しましたが、その点は確かです。不明な数の引数を関数に渡す方法は comma-separated-list generation を使用する方法であり、関数は varargin で宣言してサポートする必要があります。以下の例を更新しました。

各メインセルからランダムなサブセルを収集するヘルパー関数を作成します。

% in getRandomVectors.m
function Out = getRandomVectors(C)   % C: a double-jagged array, as described
    N   = length(C);
    Out = cell(1, N);
    for i = 1 : length(C)
        Out{i} = C{i}{randi( length(C{i}) )};
    end
end

次に、mintersect関数が次のように定義されていると仮定します。

% in mintersect.m
function Intersections = mintersect( varargin )
    Vectors = varargin;
    N = length( Vectors );
    for i = 1 : N;    for j = 1 : N
        Intersections{i,j} = intersect( Vectors{i}, Vectors{j} );
    end; end
end

次に、次のように呼び出します。

C = { { 1:5, 2:4, 3:7 }, {1:8}, {2:4, 3:9, 2:8} }; % example double-jagged array

In  = getRandomVectors(C);   % In is a cell array of randomly selected vectors
Out = mintersect( In{:} );   % Note the csl-generator syntax

PS。私はあなたのmintersectの定義がリンクされたものとは異なることに注意してください。それはあなたがあなたが何を望んでいるのかをうまく説明していなかっただけかもしれません。その場合、私のmintersect関数はあなたが望んでいるものではありません。私が行うことは、提供されたベクトルのすべての可能な交差を生成することです。リンクしたものは、提供されるすべてのベクトルに共通する単一の交差を生成します。自分に合った方を使用してください。それを使用する根本的な根拠は同じですが。

PS。また、あなたが何を求めているのかが、各nのランダムなベクトルkなのか、それともすべてのnとkにわたる可能なベクトルの空間全体なのかについても、説明から完全には明らかではありません。上記のソリューションは前者を実行します。後者が必要な場合は、代わりに、可能なすべてのインデックスのデカルト積を作成する方法に関するMadPhysicistのソリューションを参照してください。

0