2D数组上的三个嵌套循环

时间:2018-12-09 19:09:21

标签: python scipy

我有一个2D数组,它基本上表示一个函数F,该函数取决于两个变量:F(V,T)

F(V,T) is a 2D array, represented as F_VT:
F_VT   = [[F(V1), F(V2), F3(V3), ..., F(V11)], -> values for T1
          [F(V1), F(V2), F(V3)], ..., F(V11)], -> values for T2

          ...
          [F(V1), F(V2), F(V3)], ..., F(V11)] -> values for T4

V is a 1D array, V = [V1, V2, V3 ... V11]
T is a 1D array, T = [T1, T2, T3, T4]
P is a 1D array, P = [P1, P2, P3, P4]

对于给定的F(V,T),可以计算出一个新函数Fb(V,T)

Fb(V,T) = F(V,T) + P*V
  

对于TP的固定值,我想绘制Fb,并找出V达到最小值的Fb坐标。例如对于固定的TPFbV = ...达到最小值

我得出了以下三个嵌套循环:

for index_T, Ts in enumerate(T):
 for Ps in P:
  aux_P = []
  for Vs in V:
    Fb_VT = F_VT[index_T][:] + (2.293710449E+17)*(1E-21) * Ps * Vs

    p1 = plt.scatter(V, Fb_VT, color='red', marker="^", s=100)

    plt.pause(0.05)

但是曲线没有考虑P上的循环。 非常感谢您的帮助。

代码:

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

F_VT = [np.array([-941.57370763, -941.57401198, -941.57415914, -941.5741743 ,
       -941.57418547, -941.57409029, -941.57384471, -941.57349143,
       -941.57299666, -941.57242367, -941.57172351]), np.array([-941.59428621, -941.59452901, -941.59467455, -941.59470002,
       -941.59475968, -941.59472847, -941.59457033, -941.59432064,
       -941.5939331 , -941.59347988, -941.59293092]), np.array([-941.64179308, -941.64203825, -941.64223508, -941.642278  ,
       -941.64245276, -941.64254897, -941.6425414 , -941.64245835,
       -941.64223967, -941.64196782, -941.641634  ]), np.array([-941.70391106, -941.70416543, -941.70441939, -941.70448022,
       -941.70477693, -941.70500704, -941.70515626, -941.70524589,
       -941.70520195, -941.70511723, -941.70500381])]

V = np.array([ 60.208589,   60.8721745,  61.4382305,  61.515143,   62.2128025,  62.888581,
               63.567809,   64.250832,   64.937775,   65.6287725,  66.3238705])

T = np.linspace(10.00, 2000.00, 4)
P = np.linspace(1., 10., 4)

plt.figure()

for index_T, Ts in enumerate(T):
    for Ps in P:
        aux_P = []
        for Vs in V:
            Fb_VT = F_VT[index_T][:] + (2.293710449E+17)*(1E-21) * Ps * Vs

            p1 = plt.scatter(V, Fb_VT, color='red', marker="^", label='Calcite I', s=100)
            plt.pause(0.05)


plt.show()

1 个答案:

答案 0 :(得分:0)

您遇到数学问题

您没有代码问题,有数学问题。您可以通过以下数组操作获取完整的P*V值集:

((2.293710449E+17)*(1E-21) * P * V[:,None]).reshape(-1)

输出:

[0.01381011 0.05524043 0.09667075 0.13810107 0.01396231 0.05584926
 0.0977362  0.13962314 0.01409215 0.0563686  0.09864506 0.14092151
 0.01410979 0.05643917 0.09876855 0.14109793 0.01426982 0.05707926
 0.09988871 0.14269816 0.01442482 0.05769928 0.10097374 0.1442482
 0.01458061 0.05832246 0.1020643  0.14580615 0.01473728 0.05894912
 0.10316096 0.1473728  0.01489485 0.05957938 0.10426392 0.14894845
 0.01505334 0.06021336 0.10537338 0.1505334  0.01521278 0.0608511
 0.10648943 0.15212775]

请注意所有这些值有多小。现在将它们与F_VT中的值进行比较。实际上,P * V的值都比F_VT中的值小大约4个数量级。这是有道理的,因为您要将所有P * V值乘以一个1e-4数量级的常数。

我唯一可以建议的是增加VP的值。也许像P = np.linspace(1, 1000, 4)之类的东西?

通过矢量化删除循环并加速代码

这基本上与代码中的实际问题无关,但是您可以通过用两个向量化操作替换三重循环来加快处理速度:

import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

F_VT = np.array([[-941.57370763, -941.57401198, -941.57415914, -941.5741743 , -941.57418547, -941.57409029, -941.57384471, -941.57349143, -941.57299666, -941.57242367, -941.57172351], 
                 [-941.59428621, -941.59452901, -941.59467455, -941.59470002, -941.59475968, -941.59472847, -941.59457033, -941.59432064, -941.5939331 , -941.59347988, -941.59293092], 
                 [-941.64179308, -941.64203825, -941.64223508, -941.642278  , -941.64245276, -941.64254897, -941.6425414 , -941.64245835, -941.64223967, -941.64196782, -941.641634  ], 
                 [-941.70391106, -941.70416543, -941.70441939, -941.70448022, -941.70477693, -941.70500704, -941.70515626, -941.70524589, -941.70520195, -941.70511723, -941.70500381]])

V = np.array([ 60.208589,   60.8721745,  61.4382305,  61.515143,   62.2128025,  62.888581, 63.567809,   64.250832,   64.937775,   65.6287725,  66.3238705])

T = np.linspace(10.00, 2000.00, 4)
P = np.linspace(1., 10., 4)

fig = plt.figure()
ax = fig.gca()

PV = ((2.293710449E+17)*(1E-21) * P * V[:,None]).reshape(-1)
Fb_VT = (F_VT[..., None, :] + PV[None, ..., None]).reshape(-1, F_VT.shape[1])

# looping over the rows of Fb_VT will give results equivalent to the triple loop in the old code
for fbvt in Fb_VT:
    ax.scatter(V, fbvt, color='red', marker="^", label='Calcite I', s=100)

fig.show()

这将产生与您的旧代码相同的输出(尽管为了简洁起见,我将所有输出都绘制在单个图形上)

enter image description here