有没有更优雅的方式来编写这些循环?
Is there a more elegant way to write these loops?
我有一个脚本需要一些参数才能 运行。我有兴趣探索参数变化时的结果,所以我在顶部定义了几个 scan
数组,将整个代码包装在多个 for loops
中并将参数值设置为当前扫描值。
这很容易出错而且不优雅。更改代码的过程是:1) 在顶部重置 scan
变量,2) 注释掉例如 b = scan2(j2)
和 3) 取消注释 b=b0
。
允许将变量设置为数组以及随后 运行 所有此类组合的代码的更好方法是什么? 现在我的代码示例:
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
一种方法是使用 ndgrid 制作一个包含所有参数组合的向量。对于足够大的参数扫描,这可能会成为内存问题,但至少在其他方面更清晰,只需要一个循环,代码后面不需要 re-assignments:
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
仍然希望看到您的建议!
基于this idea用一个for循环模拟多个循环,我试着适应你的情况。虽然实现了良好的内存效率和可用性,但此解决方案比使用单独的 for 循环要慢。
%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
对于我测试的场景,每次迭代增加的计算开销低于 0.0002
s,总共 0.0002.*prod(iterations)
s。
我有一个脚本需要一些参数才能 运行。我有兴趣探索参数变化时的结果,所以我在顶部定义了几个 scan
数组,将整个代码包装在多个 for loops
中并将参数值设置为当前扫描值。
这很容易出错而且不优雅。更改代码的过程是:1) 在顶部重置 scan
变量,2) 注释掉例如 b = scan2(j2)
和 3) 取消注释 b=b0
。
允许将变量设置为数组以及随后 运行 所有此类组合的代码的更好方法是什么? 现在我的代码示例:
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
一种方法是使用 ndgrid 制作一个包含所有参数组合的向量。对于足够大的参数扫描,这可能会成为内存问题,但至少在其他方面更清晰,只需要一个循环,代码后面不需要 re-assignments:
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
仍然希望看到您的建议!
基于this idea用一个for循环模拟多个循环,我试着适应你的情况。虽然实现了良好的内存效率和可用性,但此解决方案比使用单独的 for 循环要慢。
%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
对于我测试的场景,每次迭代增加的计算开销低于 0.0002
s,总共 0.0002.*prod(iterations)
s。