Is there a more elegant way to write these loops?

南笙酒味 提交于 2019-12-12 02:39:19

问题


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

回答1:


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.0002s per iteration which is 0.0002.*prod(iterations)s in total.




回答2:


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!



来源:https://stackoverflow.com/questions/34839668/is-there-a-more-elegant-way-to-write-these-loops

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!