Три вложенных цикла над двумерным массивом - PullRequest
0 голосов
/ 09 декабря 2018

У меня есть 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

Для фиксированных значений T и P я хотел бы построить Fb и отсортировать координаты V, где Fbдостигает минимума.например, для фиксированных T и P, Fb достигает минимума при V = ...

Я получил следующие три вложенных цикла:

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 голосов
/ 10 декабря 2018

У вас математическая проблема

У вас нет проблемы с кодом, у вас есть математическая проблема.Вы можете получить полный набор ваших 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 на самом деле примерно на 4 порядка меньше значений в F_VT.Это имеет смысл, так как вы умножаете все свои значения P * V на постоянный коэффициент порядка 1e-4.

Единственное, что я могу предложить, это увеличить либо значения V, либо P.Может быть, что-то вроде 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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...