简体   繁体   中英

Conditional selection of all possible parameter combinations in MATLAB

This is a follow-up of the question All possible combinations of many parameters MATLAB

In addition to all possible combinations of my parameter set, I also have a conditional parameter. For example, I need to include the parameter named 'lambda' only when the parameter 'corrAs' is set to 'objective'.

Do achieve this, right now I am doing the following

%% All posible 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'};  

% If corrAs is 'objective', then also set lambda
params.lambda = {0.01, 0.1, 1, 10, 100};

%%%%%%%%%%%%% The solution posted on the link %%%%%%%%%%%
%% Get current parameter and evaluate
fields = fieldnames(params);
nFields = numel(fields);
sz = NaN(nFields, 1);

% Loop over all parameters to get sizes
for jj = 1:nFields
    sz(jj) = numel( params.(fields{jj}) );
end

% Loop for every combination of parameters
idx = cell(1,nFields);
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:nFields

        %%%%%%%%%%% My addition for conditional parameter %%%%%%%%%%%
        % lambda is valid only when corrAs is 'objective'
        if isfield(currentParam, 'corrAs') && strcmp(fields{jj}, 'lambda') && ~strcmp(currentParam.corrAs, 'objective')
            continue;
        end
        currentParam.(fields{jj}) = params.(fields{jj}){idx{jj}};
    end

    %% Do something with currentParam

end

It works but, the number of iterations for the main for loop also includes the lambda parameter even when corrAs is not 'objective'. So, I end up evaluating with the same currentParam many times than I am supposed to.

How can I do it more efficiently?

An easy way to think about this is by breaking the code up to be more function-based

In the below code, I've simply put the combination processing code into a function paramProcessing . This function is called twice -

  1. When params.corrAs is 'constraint' only, all combinations will be processed, with no lambda field.

  2. When params.corrAs is 'objective' only, all combinations will be processed with the additional lambda field.

You can have an output for the paramProcessing function if there is one from the looping.

This means you're only doing the combinations you want. From your question, it seems like each combination is independent, so it should be irrelevant that you're covering the combinations in separate loops. The function usage means you don't have to have the new condition in the loop, and the distinct possible values for params.corrAs each time ensure no overlap.

The paramProcessing function can be a local function in a main function file, as shown, local in a script (for newer MATLAB versions), or in its own .m file on your path.

Code:

function main()
    %% All posible parameters, corrA is 'constraint' only.
    params.corrAs = {'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'};  

    % First processing call, no 'lambda' field exists in 'params'
    paramProcessing( params );

    % Cover the cases where corrAs is 'objective', with 'lambda' field
    params.corrAs = {'objective'};
    params.lambda = {0.01, 0.1, 1, 10, 100};

    % Second processing call, with new settings
    paramsProcessing( params );    
end
function paramProcessing( params )
    %% Get current parameter and evaluate
    fields = fieldnames(params);
    nFields = numel(fields);
    sz = NaN(nFields, 1);

    % Loop over all parameters to get sizes
    for jj = 1:nFields
        sz(jj) = numel( params.(fields{jj}) );
    end

    % Loop for every combination of parameters
    idx = cell(1,nFields);
    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:nFields
            currentParam.(fields{jj}) = params.(fields{jj}){idx{jj}};
        end

        %% Do something with currentParam

    end
end    

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM