执行输入参数的所有可能排列(二进制样式逻辑)

Posted

技术标签:

【中文标题】执行输入参数的所有可能排列(二进制样式逻辑)【英文标题】: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,则它需要能够适应,依此类推。我已经考虑将其作为循环或递归进行,但我认为作为循环会更容易理解,但两者都非常有用。 我不想手动执行此操作,因此非常感谢任何帮助。

【问题讨论】:

varargin 【参考方案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
[paramCombsend:-1:1] = ndgrid(paramsend:-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(paramCombsn,:), 1:N, 'uni', 0); %// call myFun
%// with each combination of parameter values

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

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

>> result1
ans =
     0    20     6
>> result2
ans =
     0    20    36
>> result3
ans =
     0    20    66
>> result4
ans =
     0    30     6
>> result5
ans =
     0    30    36

等等

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

>> result1
ans =
     0     0
>> result2
ans =
     0     5
>> result3
ans =
     0    10
>> result4
ans =
     1     0
>> result5
ans =
     1     5

等等

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

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

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

>> result1
ans =
     1    10
>> result2
ans =
     1    20
>> result3
ans =
     2    10
>> result4
ans =
     2    20
>> result5
ans =
     3    10
>> result6
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)

ans1 =

    10    30     6

ans2 =

    10    20    36

ans3 =

     5    40     6

ans4 =

     5    20    66

ans5 =

     0    30    66

ans6 =

     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 是一个肮脏的解决方案,但我找不到允许可变输入大小的替代方案。

【讨论】:

以上是关于执行输入参数的所有可能排列(二进制样式逻辑)的主要内容,如果未能解决你的问题,请参考以下文章

卡诺图简单逻辑化简与五变量卡诺图化简

LeetCode 0784. 字母大小写全排列:二进制枚举

计算具有相同汉明权重的二进制数的所有排列的最快算法是啥?

具有多个列表的递归排列

lua 二进制的移位运算

matlab中1和0等概率的所有组合的二进制矩阵