当输入参数数量未知时,使用可变数量的输入参数进行函数调用

am304

我有一个变量pth,它是维的单元格数组,1xn其中n是用户输入。中的每个元素pth本身就是一个单元数组,并且length(pth{k})fork=1:n是可变的(另一个函数的结果)。每个元素pth{k}{kk}其中k=1:nkk=1:length(pth{k})是一个一维向量,该向量是整数/节点号,且长度可变。因此,总而言之,我将可变数目的可变长度向量组织在大量的单元格数组中。

我想尝试并找到所有可能的十字路口,当你把一个向量从随机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...

继续研究所有可能的组合,但是我无法用代码编写。来自File Exchange的函数看起来是查找所有可能组合的好方法,但是同样,对于可变数量输入的函数调用,我也遇到相同的问题:

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

当您无法物理地指定所有输入参数,因为它们的数量是可变的时,有人知道如何解决带有可变数量的输入参数的函数调用的问题吗?这同样适用于MATLAB和Octave,因此也适用于两个标签。关于从每次pth{k}欢迎中随机抽取向量时如何找到所有可能的组合/交叉点的任何其他建议

编辑27/05/20

感谢Mad Physicist的回答,我最终使用了以下有效的方法:

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和的4个元素pth2x19x18x169x1),我得到了以下结果:

>> benchmark

Elapsed time is 51.9075 seconds.
valid_comb =  7112

Elapsed time is 66.6693 seconds.
valid_comb =  7112

因此,疯狂物理学家的方法要快15秒钟左右。

我也误解了mintersect那是什么,那不是我想要的。我想找到一个组合,其中两个或多个向量中不存在任何元素,因此我结束了我的版本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
疯狂物理学家

构建解决方案的几个有用点:

  • 这篇文章向您展示了如何使用构造任意数组之间的笛卡尔积ndgrid
  • cellfun 同时接受多个单元格数组,可用于索引特定元素。
  • 您可以使用电池阵列从一个函数捕获可变数量的参数,如图所示这里

因此,让我们ndgrid从最外面的数组获取输入

grids = cellfun(@(x) 1:numel(x), pth, 'UniformOutput', false);

现在,您可以创建一个包含网格乘积的索引:

index = cell(1, numel(pth));
[index{:}] = ndgrid(grids{:});

您想将所有网格变成列向量并将其横向连接。该矩阵的行将代表笛卡尔索引,以便pth在每次迭代时选择的元素

index = cellfun(@(x) x(:), index, 'UniformOutput', false);
index = cat(2, index{:});

如果将一行index转换为一个单元格数组,则可以pth逐步进行操作以选择正确的元素并调用mintersect结果。

for i = index'
    indices = num2cell(i');
    selection = cellfun(@(p, i) p{i}, pth, indices, 'UniformOutput', false);
    mintersect(selection{:});
end

这是在假设pth是行数组的情况下编写的如果不是这种情况,则可以将循环的第一行更改indices = reshape(num2cell(i), size(pth));为一般情况,而仅indices = num2cell(i);将列情况更改为。关键是from的单元格indices必须具有相同的形状,pth以便在步调上对其进行迭代。它已经生成为具有相同数量的元素。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章