matlab - 当未明确知道输入参数的数量时,使用可变数量的输入参数调用函数

标签 matlab octave function-call

我有一个变量 pth,它是维度为 1xn 的元胞数组,其中 n 是用户输入。 pth 中的每个元素本身都是元胞数组,length(pth{k}) for k=1:n 是可变的(结果另一个功能)。每个元素 pth{k}{kk} 其中 k=1:nkk=1:length(pth{k}) 是一个整数的一维向量/再次可变长度的节点号。因此,总而言之,我有可变数量的可变长度向量,它们组织在可变数量的元胞数组中。

当您从 pth{1}, pth{2}, {pth 中随机选取一个向量时,我想尝试找到所有可能的交叉点{3} 等...文件交换上有各种功能似乎可以做到这一点,例如 this onethis one .我遇到的问题是您需要以这种方式调用该函数:

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

而且我不能在一般情况下写出所有输入,因为我不知 Prop 体有多少(这将是上面的 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来自 File Exchange 看起来是找到所有可能组合的好方法,但我再次遇到具有可变输入数量的函数调用的相同问题:

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

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

编辑 2020 年 5 月 27 日

感谢疯狂物理学家的回答,我最终使用了以下有效的方法:

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 个元素为 2x19x18x169x1),我得到了以下结果:

>> benchmark

Elapsed time is 51.9075 seconds.
valid_comb =  7112

Elapsed time is 66.6693 seconds.
valid_comb =  7112

所以疯狂物理学家的方法快了大约 15 秒。

我也误解了 mintersect 所做的,这不是我想要的。我想找到一个组合,其中两个或多个向量中不存在任何元素,所以我结束了编写我的 minintersect 版本:

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

最佳答案

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

  • This post向您展示如何使用 ndgrid 在任意数组之间构造笛卡尔积.
  • cellfun 同时接受多个元胞数组,您可以使用它们来索引特定元素。
  • 您可以使用元胞数组从函数中捕获可变数量的参数,如图所示 here .

那么让我们输入 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);对于列的情况。关键是来自 indices 的单元格形状必须与 pth 相同同步迭代它。它已经生成为具有相同数量的元素。

关于matlab - 当未明确知道输入参数的数量时,使用可变数量的输入参数调用函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61964257/

相关文章:

matlab - 在带有 GPU 加速的 arrayfun 中使用匿名函数 (Matlab)

matlab - Matlab 中的二维 body 变换和旋转

regex - 如何使用Matlab/Octave regexprep(正则表达式替换)在文件名扩展名前添加后缀

matlab - 自由垫 : How different is it from Octave?

syntax-highlighting - 如何在 Octave 中获得颜色和语法高亮显示?

c++ - 是否可以显式调用名称损坏函数?

java - 错过的函数调用导致堆栈溢出

c# - numpy 的日志函数发生了什么?有没有办法提高性能?

matlab - 在 MATLAB 中通过 HTTP 接收数据

java - 从许多类的类中调用函数而无需重置值