Reputation: 11181
I have a script that requires a handful of parameters to run. I'm interested in exploring the results as the parameters change, so I define a few scan
arrays at the top, wrap the whole code in multiple for loops
and set the parameters values to the current scan values.
This is error prone and inelegant. The process for changing the code is: 1) reset scan
variables at the top, 2) comment out eg b = scan2(j2)
and 3) uncomment b=b0
.
What's a better method to allow variables to be set to arrays, and subsequently run the code for all such combinations? Example of my code now:
close all
clear all
%scan1 = linspace(1,4,10);
scan1 = 0;
scan2 = linspace(0,1,10);
scan3 = linspace(-1,0,10);
for j3 = 1:length(scan3)
for j2 = 1:length(scan2)
for j1 = 1:length(scan1)
a = a0;
%b = scan2(j2);
b = b0;
%c = c0;
c = scan3(j3);
d = scan2(j2);
%(CODE BLOCK THAT DEPENDS ON variables a,b,c,d...)
end
end
end
Upvotes: 0
Views: 138
Reputation: 36720
Based on this idea to use one for loop to simulate multiple loops, I tried to adapt it to your case. While fulfilling a good memory efficiency and usability, this solution is slower than using individual for loops.
%define your parameters
p.a = 1;
p.b = linspace(1,4,4);
p.c = linspace(11,15,5);
p.d = linspace(101,104,4);
p.e = 5;
iterations=structfun(@numel,p);
iterator=cell(1,numel(iterations));
for jx = 1:prod(iterations)
[iterator{:}]=ind2sub(iterations(:).',jx);%.'
%This line uses itertor to extract the corresponding elemets of p and creates a struct which only contains scalars.
q=cell2struct(cellfun(@(a,b)(a(b)),struct2cell(p),iterator(:),'uniform',false),fieldnames(p));
%__ (CODE THAT DEPENDS ON q.a to q.e here) __
end
For the scenarios I tested it adds an computation overhead below 0.0002
s per iteration which is 0.0002.*prod(iterations)
s in total.
Upvotes: 4
Reputation: 11181
One method is to make a single vector that contains all the parameter combinations, using ndgrid. For a sufficiently large parameter scans this may become a memory concern, but otherwise is at least much cleaner, requiring only a single loop and no re-assignments later in the code:
a0vec = 1;
b0vec = linspace(1,4,4);
c0vec = linspace(11,15,5);
d0vec = linspace(101,104,4);
e0vec = 5;
[a0s,b0s,c0s,d0s,e0s] = ndgrid(a0vec,b0vec,c0vec,d0vec,e0vec);
N = numel(a0s);
for j = 1:N
a0 = a0s(j);
b0 = b0s(j);
c0 = c0s(j);
d0 = d0s(j);
e0 = e0s(j);
%__ (CODE THAT DEPENDS ON a0 - e0 here) __
end
Would still like to see your suggestions!
Upvotes: 0