存储来自三重 for 循环的数据

Posted

技术标签:

【中文标题】存储来自三重 for 循环的数据【英文标题】:Store data from a triple for loop 【发布时间】:2019-04-18 17:45:30 【问题描述】:

我有我在 MATLAB 中编写的用于存储矩阵的代码。我使用的是单元格数组,但在 Python 中我不知道该怎么做。

有人知道我该怎么做吗?

MATLAB 代码为:

S =[0.5 0.7 0.9 1.1]; % distância entre tx e rx[m]
d = 0.2*ones(1,10); 
h = [ 0 0.1 0.2 0.3 0.4]

n_cam = length(d); % numero de camadas
n_alt = length(h); % numero de alturas
n_S = length(S); % numero de receptores
z = zeros(n_cam,n_alt); % profundidade
Rv_h = zeros(n_S,n_alt);
Rv_v = zeros(n_S,n_alt);
Rv = zeros(n_cam,n_alt);
Rh = zeros(n_cam,n_alt);
S_Rv = cell(1,n_S);
S_Rh = cell(1,n_S);
sigma = 0.3*ones(1,n_cam);
sigmaah = zeros(n_S,n_alt);


for i = 1:n_S
    for  j = 1:n_alt
        for k = 1:n_cam
            z(k,j)= (sum(d(1:k))+h(j))/S(i);
            Rv(k,j) = 1/((4*z(k,j)^2+1)^0.5);
            Rh(k,j) = ((4*z(k,j)^2+1)^0.5)-2*z(k,j);
        end 
        Rv_h(i,j) = 1/((4*(h(j)/S(i))^2+1)^0.5);
        Rh_h(i,j)=((4*(h(j)/S(i))^2+1)^0.5)-2*(h(j)/S(i));
    end
    S_Rv(:,i) = Rv; % z para cada camada em cada altura, para cada S
    S_Rh(:,i) = Rh;
end

for i = 1:n_S
    for  j = 1:n_alt
        Rv = cell2mat(S_Rv(1,i));
        Rh = cell2mat(S_Rh(1,i));
        sigma_ah = sigma(1)*(Rh_h(i,j)-Rh(1,j));
        sigma_av = sigma(1)*(Rv_h(i,j)-Rv(1,j));
        for k = 2:(n_cam-1)
           sigma_ah_ant = sigma_ah;
           sigma_av_ant = sigma_av;
           sigma_ah = sigma_ah_ant + sigma(k)*(Rh(k-1,j)-Rh(k,j));
           sigma_av = sigma_av_ant + sigma(k)*(Rv(k-1,j)-Rv(k,j));
        end
        sigmaah (i,j)  = sigma_ah + sigma(end)*Rh(n_cam-1,j)
        sigmaav (i,j)  = sigma_av + sigma(end)*Rv(n_cam-1,j)
    end
end

我在想,在 Python 中我可以做类似的事情:

n_S = 4
n_alt = 9
n_cam = 6
Rv =[]
for i in range(1,n_S):
    for j in range(1,n_alt):
        for k in range(1,n_cam):
            z[k][j]= (sum(d[0:k])+h[j])/S[i]
            Rv[i][j][k] = 1/((4*z[k,j]**2+1)**0.5)

但它不起作用,我得到的错误消息是

列表索引超出范围。

【问题讨论】:

您似乎没有定义几个变量(或函数,不确定是哪个)(至少在这段代码 sn-p 中):zd 就在其中。另外,“它不起作用”是什么意思?您是否看到了具体的错误消息? 缺少 z d h S 定义。也正如@JonahBishop 所说,什么是“不工作”? 我没有放所有代码...d = 0.2*ones(1,10), h = [ 0 0.1 0.2 0.3 0.4] z 是从 d 和 h 计算出来的 把所有的代码都放好,这样我们就可以帮助你了。 @antfuentes87 完成! =) 【参考方案1】:

在执行此操作之前,您需要将 zRv 定义为已知大小的 2D 和 3D 数组。

还要注意,python(和 numpy)数组是从零开始的,所以直接使用 range

未测试:

import numpy as np

d = 0.2*np.arange(10)   ### not sure if this is what you meant
h = np.array([ 0 0.1 0.2 0.3 0.4])

n_S = 4
n_alt = 9
n_cam = 6
Rv = np.zeros((n_S, n_alt, n_cam))
z = np.zeros((n_cam, n_alt))
for i in range(n_S):
    for j in range(n_alt):
        for k in range(n_cam):
            z[k][j]= (sum(d[0:k])+h[j])/S[i]   ## not sure about 0:10
            Rv[i][j][k] = 1/((4*z[k,j]**2+1)**0.5)

然而,正如@GlobalTraveler 指出的那样,最pythonic/numpyish 的方法是利用广播而不使用循环:

Rv = 1/np.sqrt(4 * z**2 + 1)

【讨论】:

【参考方案2】:

我建议使用broadcasting 功能

然后可以替换循环以澄清代码:

from numpy import array, ones
S =array([0.5, 0.7, 0.9, 1.1])
d = 0.2*ones((10)); 
h = array([ 0, 0.1, 0.2, 0.3, 0.4])

z = ((d.cumsum()[:, None] + h).ravel() / S[:, None]).reshape((S.size, d.size, h.size))
Rv = 1 / (4 * z ** 2 + 1)** .5
# ...etc
print(Rv[-1])

哪些输出:

    [[0.93979342 0.87789557 0.80873608 0.73994007 0.67572463]
 [0.80873608 0.73994007 0.67572463 0.61782155 0.56652882]
 [0.67572463 0.61782155 0.56652882 0.52145001 0.48191875]
 [0.56652882 0.52145001 0.48191875 0.4472136  0.41665471]
 [0.48191875 0.4472136  0.41665471 0.38963999 0.36565237]
 [0.41665471 0.38963999 0.36565237 0.34425465 0.32507977]
 [0.36565237 0.34425465 0.32507977 0.30782029 0.29221854]
 [0.32507977 0.30782029 0.29221854 0.27805808 0.26515648]
 [0.29221854 0.27805808 0.26515648 0.25335939 0.24253563]
 [0.26515648 0.25335939 0.24253563 0.23257321 0.22337616]]

与octave/matlab中的计算重叠:

Rv =

   0.93979   0.87790   0.80874   0.73994   0.67572
   0.80874   0.73994   0.67572   0.61782   0.56653
   0.67572   0.61782   0.56653   0.52145   0.48192
   0.56653   0.52145   0.48192   0.44721   0.41665
   0.48192   0.44721   0.41665   0.38964   0.36565
   0.41665   0.38964   0.36565   0.34425   0.32508
   0.36565   0.34425   0.32508   0.30782   0.29222
   0.32508   0.30782   0.29222   0.27806   0.26516
   0.29222   0.27806   0.26516   0.25336   0.24254
   0.26516   0.25336   0.24254   0.23257   0.22338   

这减少了厄运金字塔,并且由于 numpy 魔法可能比 for 循环更快。 编辑:格式化 Edit2:给了检查

【讨论】:

我不懂代码,适用于存储数据,但 Rv 结果与 matlab 不一样...... d.cumsum() 一直到它应该的索引? 我的括号错了。编辑了上面的代码 sn-p 以匹配您的行。本质上它的工作原理类似于 matlab 中的 bsxfun。我反复对其他维度进行操作。 .cumsum() 执行与您正在执行的操作类似的累积和。唯一的区别是我的结果是沿第三轴附加的。由于您正在覆盖 z 矩阵,因此您不使用它。 还添加了最后一次迭代输出的确认 非常感谢!效果很好!这远远超出了我在 python 方面的知识 没问题。请注意,这是 numpy 魔术,不一定是 python。与普通列表相比,Numpy 数组对于数值计算非常有用。

以上是关于存储来自三重 for 循环的数据的主要内容,如果未能解决你的问题,请参考以下文章

Sum Zero Problem(三数和为0, 破解三重for循环问题)

三重嵌套循环中的这条语句执行多少次?

opencv C++ 三重for循环遍历RGB图像像素(逐像素操作操作像素值遍历像素遍历)

矩阵k次幂 采用三重循环

图数据库与三重存储 - 何时使用哪个?

Metal 最佳实践:三重缓冲 – 纹理?