【问题标题】:Execute all possible permutations of input parameters (binary style logic)执行输入参数的所有可能排列(二进制样式逻辑)
【发布时间】:2014-03-15 06:28:55
【问题描述】:

我正在尝试编写一些代码来为具有未知数量参数的函数提供数据。这个想法是在可能的值范围内为函数提供最小值、中间值和最大值。

例如:

  • 如果函数采用 3 个参数
  • 参数 1 可以接受的范围是 0 - 10
  • 参数 2 可以接受的范围是 20 - 40
  • 参数 3 可接受的范围为 6 - 66

myfunction(para1, para2, para3)
我的函数(分钟,分钟,分钟)
我的函数(分钟,分钟,中间)
我的函数(最小值、最小值、最大值)
我的函数(分钟,中,分钟)
我的功能(分钟,中,中)
我的函数(最小值、中间值、最大值)
等等……

所以使用我们上面的例子:

第一次循环时我需要运行
我的函数(0, 20, 0)
下次循环它需要运行
我的函数(0, 20, 36)
下次循环它需要运行
我的函数(0, 20, 66)
等等...

对于所有可能的组合(在本例中为所有 27 个)。
但是,如果参数的数量更改为接受 4,则它需要能够适应,依此类推。我已经考虑将其作为循环或递归进行,但我认为作为循环会更容易理解,但两者都非常有用。

我不想手动执行此操作,因此非常感谢任何帮助。

【问题讨论】:

标签: matlab loops combinations


【解决方案1】:

对于任意数量的参数(不固定为3),可以使用以下代码。它利用comma-separated lists,这是一个处理可变数量参数的强大工具。

设 n 为参数的数量。那么组合的数量是N = 3^n。

params = {linspace(0,10,3), linspace(20,40,3), linspace(6,66,3)};
%// cell array with arbitrary number of elements. Each cell contains a 3-vector
%// which defines min, mid, max of one parameter.

n = numel(params); %// number of parameters
N = 3^n; %// number of combinations
paramCombs = cell(1,n); %// initialization for output of ndgrid
[paramCombs{end:-1:1}] = ndgrid(params{end:-1:1}); %// generate all combinations
%// in desired order. Gives n matrices, each containing values of one parameter
paramCombs = cellfun(@(c) c(:), paramCombs, 'uni', 0); %// linearize matrices
%// into n column vectors, each with N rows.
paramCombs = [paramCombs{:}]; %// concat column vectors into N x n matrix
paramCombs = mat2cell(paramCombs,ones(N,1),ones(n,1)); %// convert to
%// N x n cell array. Each row contains a combination of parameter values
result = arrayfun(@(n) myFun(paramCombs{n,:}), 1:N, 'uni', 0); %// call myFun
%// with each combination of parameter values

result 变量是一个 1 x N 元胞数组,其中每个元胞包含调用 myFun 并结合 n 个参数的结果。

示例 1myFun 的输出只是简单地复制了输入(如 @thewaywewalk's answer)。 params定义如上,所以有3个参数:

>> result{1}
ans =
     0    20     6
>> result{2}
ans =
     0    20    36
>> result{3}
ans =
     0    20    66
>> result{4}
ans =
     0    30     6
>> result{5}
ans =
     0    30    36

等等

示例 2:带有 2 个参数的案例:params = {linspace(0,2,3), linspace(0,10,3)}。同样,myFun 只是复制输入:

>> result{1}
ans =
     0     0
>> result{2}
ans =
     0     5
>> result{3}
ans =
     0    10
>> result{4}
ans =
     1     0
>> result{5}
ans =
     1     5

等等

该方法可以进一步推广到每个参数的任意(可能不同)数量的值,只需将N = 3^n;行替换为

N = prod(cellfun(@numel, params)); %// number of combinations

示例3:有2个参数;第一个有 3 个值,第二个有 2 个:params = {[1 2 3], [10 20]};:

>> result{1}
ans =
     1    10
>> result{2}
ans =
     1    20
>> result{3}
ans =
     2    10
>> result{4}
ans =
     2    20
>> result{5}
ans =
     3    10
>> result{6}
ans =
     3    20

【讨论】:

    【解决方案2】:

    想想这样的事情:

    function result = permfunction() 
    
    % I assume you every parameter-range is defined by 3 values: min, mid, max
    % you can define every triple as follows:
    para1 = linspace(0,10,3);
    para2 = linspace(20,40,3);
    para3 = linspace(6,66,3);
    
    % all possible parameters
    parameters = [para1(:),para2(:),para3(:)];
    
    % possible combinations of parameters-indices
    a = perms(1:3);  
    % transformed into a cell array with linear indices, to achieve this +3 and +6 
    % are added to the 2nd and 3rd row.
    
    idx = mat2cell( [a(:,1) , a(:,2)+3 , a(:,3)+6] , ones(length(a),1) );
    
    % all parameter combinations
    combinations = cellfun(@(x) parameters(x),idx,'uni',0');
    
    % apply to your function myfunction (custom)
    result = cellfun(@myfunction, combinations,'uni',0' );
    
    end
    
    function y = myfunction( parametertriple )
    
    %just pass the input to the output
    y = parametertriple;
    
    end
    

    您最终会得到一个元胞数组,其中包含所有参数组合的 myfunction 结果。在这种情况下,我只是将参数传递给输出:

    >> celldisp(ans)
    
    ans{1} =
    
        10    30     6
    
    ans{2} =
    
        10    20    36
    
    ans{3} =
    
         5    40     6
    
    ans{4} =
    
         5    20    66
    
    ans{5} =
    
         0    30    66
    
    ans{6} =
    
         0    40    36
    

    【讨论】:

    • +1 不错的方法。可以使用逗号分隔的列表推广到不确定数量的参数;看我的回答
    【解决方案3】:

    这就是我的解决方法:

    %dummy function
    testfun=@(a,b,c)fprintf('call function for %d,%d,%d\n',a,b,c);
    %functon name
    testfunname='testfun';
    %intended inputs
    input={[0,5,10],[20,30,40],[6,36,66]};
    %generate all inputs
    eval(['[' sprintf('a{%d} ',1:numel(input)) ']=meshgrid(input{:});']);
    %call function
    eval(['arrayfun(' testfunname sprintf(',a{%d} ',1:numel(input)) ');']);
    

    使用eval 是一个肮脏的解决方案,但我找不到允许可变输入大小的替代方案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-03-27
      • 2015-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多