许多参数的所有可能组合MATLAB

时间:2019-01-07 10:15:10

标签: matlab struct

我有一个参数列表,我需要在该列表上评估我的方法。现在,我正在这样做

% Parameters
params.corrAs = {'objective', 'constraint'};
params.size = {'small', 'medium', 'large'};
params.density = {'uniform', 'non-uniform'};
params.k = {3,4,5,6};
params.constraintP = {'identity', 'none'};
params.Npoints_perJ = {2, 3};
params.sampling = {'hks', 'fps'};   

% Select the current parameter
for corrAs_iter = params.corrAs
    for size_iter = params.size
        for density_iter = params.density
            for k_iter = params.k
                for constraintP_iter = params.constraintP
                    for Npoints_perJ_iter = params.Npoints_perJ
                        for sampling_iter = params.sampling
                            currentParam.corrAs = corrAs_iter;
                            currentParam.size = size_iter;
                            currentParam.density = density_iter;
                            currentParam.k = k_iter;
                            currentParam.constraintP = constraintP_iter;
                            currentParam.Npoints_perJ = Npoints_perJ_iter;
                            currentParam.sampling = sampling_iter;
                            evaluateMethod(currentParam);
                        end
                    end
                end
            end
        end
    end
end

我知道它看起来很丑陋,如果我想添加新类型的参数,则必须编写另一个for循环。有什么办法,我可以向量化吗?或者也许使用2个for循环而不是那么多。

我尝试了以下操作,但是并不能满足我的需要。

for i = 1:numel(fields)
%     if isempty(params.(fields{i}))
    param.(fields{i}) = params.(fields{i})(1);
    params.(fields{i})(1) = [];
end

2 个答案:

答案 0 :(得分:5)

您需要的是all combinations个输入参数。不幸的是,随着添加更多参数,存储需求将迅速增长(并且您将不得不使用大型索引矩阵)。

相反,这是一个使用(从未创建的)function find(object, value) { return Object .keys(object) .find(k => [].concat(object[k]).includes(value)); } var object = { FOO: { BAR: [9, 32, 8, 12], ZET: 4, BETA: [3, 14, 6, 2], ALPHA: 37 } }; console.log(find(object.FOO, 4)); console.log(find(object.FOO, 8));矩阵的线性索引的想法,其中n1*n2*...*nmni字段中每个字段中的元素数。

它足够灵活,可以应付添加到m的任何数量的字段。未经性能测试,尽管与任何“所有组合”操作一样,您应该警惕在向params添加更多字段时计算时间的非线性增加,请注意params

我显示的代码很快,但是性能将完全取决于您在循环中执行的操作。

prod(sz)

除:

  • 我正在使用dynamic field name references为字段建立索引
  • 我要从% Add parameters here params.corrAs = {'objective', 'constraint'}; params.size = {'small', 'medium', 'large'}; params.density = {'uniform', 'non-uniform'}; % Setup f = fieldnames( params ); nf = numel(f); sz = NaN( nf, 1 ); % Loop over all parameters to get sizes for jj = 1:nf sz(jj) = numel( params.(f{jj}) ); end % Loop for every combination of parameters idx = cell(1,nf); for ii = 1:prod(sz) % Use ind2sub to switch from a linear index to the combination set [idx{:}] = ind2sub( sz, ii ); % Create currentParam from the combination indices currentParam = struct(); for jj = 1:nf currentParam.(f{jj}) = params.(f{jj}){idx{jj}}; end % Do something with currentParam here % ... end 传递multiple outputs into a cell array,所以当ind2sub每个维度(或本用例中的字段)有一个输出时,您可以处理可变数量的字段名称。

答案 1 :(得分:3)

这是向量化的解决方案:

names = fieldnames(params).';
paramGrid = cell(1,numel(names));

cp = struct2cell(params);

[paramGrid{:}] = ndgrid(cp{:});

ng = [names;paramGrid];
st = struct(ng{:});


for param = st(:).'
    currentParam = param;
end

我们可以使用ndgrid来创建单元格条目的笛卡尔积,而不是嵌套循环,因此我们可以找到没有循环的所有单元格条目组合。