Python 效率 - 带矩阵的嵌套循环结构

问题描述 投票:0回答:1

我是 Python 新手,但多年来一直在 MATLAB 中进行编码。我一直在努力编写一个特定问题的代码,该问题需要多个矩阵的嵌套 for 循环来求解一系列方程。我知道如何在 MATLAB 中对其进行编码,然后使用 chatGPT 帮助转换为 python 语法。我正在使用 Spyder 界面和 python 3.9。下面显示了此处描述的相关代码,我想了解使其运行更高效的具体方法。我已经使用 itertools 阅读了之前类似问题的答案,但应用后,它们似乎不起作用。

import numpy as np

R1init=[]
R2init=[]
L1init=[]
L2init=[]
p1init=[]
p2init=[]
m1init=[]
m2init=[]
dVrinit=[]
dVlinit=[]

R1 = np.arange(50, 200.001, 2)
R2 = R1  # Since R1 and R2 are identical
L1 = -1*R1
L2 = np.arange(-50,-300.001,-10)

#converted values to be thousands, assuming this would help with matrix sizes.
dVl = 194329/1000  
dVr = 51936/1000  
dVg = 188384/1000  
DR = 0. 
DB = 0.

m1 = np.abs(dVl / R1) 
m2 = np.abs(dVr / L2)


j1 = 0
j2 = 0

for i in R1:
    for j in R2:
        for k in L1:
            for m in L2:
                for n in m1:
                    for q in m2:
                        p1 = ((j2*(1+q)-q)*m+j+dVr)/i
                        p2 = 1-j2*(1+q)+q-(i/m)*(1-j1*(1+n)+n-p1)+dVg/m
                        dVrchk = (q-(j2*q)-q)*m+(p1*i)-j+DR+DB
                        dVlchk =(j1-n+(j1*n))*i+k-(p2*m)
                        dVgchk = (1-j1-p1+n-j1*n)*i-(1-j2-p2+q-j2*q)*m
                        if 0<p2<1.05 and 0<p1<1.05 and dVl-100<dVlchk<dVl+100 and dVr-  100<dVrchk<dVr+100:
                            R1init.append(i)
                            R2init.append(j)
                            L1init.append(k)
                            L2init.append(m)
                            p1init.append(p1)
                            p2init.append(p2)
                            m1init.append(n)
                            m2init.append(q)
                            dVrinit.append(dVrchk)
                            dVlinit.append(dVlchk)
python numpy nested-loops processing-efficiency
1个回答
0
投票

我建议使用 Numba 来加快速度,并更改检查条件的顺序。这足以在一秒钟内解决此问题。

例如,您对

p1
的条件不涉及变量
n
k
,因此您无需循环遍历这些变量的所有组合来检查它们。

同样,

p2
不依赖于
k
,因此可以在
k
循环之外完成。

这确实有一个缺点,它改变了解决方案的顺序,但我猜你不太关心它们返回的顺序。

这些优化可以在一秒钟内完成。

import numba as nb
from numba.typed import List


@nb.njit()
def search_inner(R1, R2, L1, L2, m1, m2):
    dVl = 194329/1000
    dVr = 51936/1000
    dVg = 188384/1000
    DR = 0. 
    DB = 0.

    R1init = List()
    R2init = List()
    L1init = List()
    L2init = List()
    p1init = List()
    p2init = List()
    m1init = List()
    m2init = List()
    dVrinit = List()
    dVlinit = List()
    j1 = 0
    j2 = 0

    for i in R1:
        for j in R2:
            for q in m2:
                for m in L2:
                    # i j q m
                    p1 = ((j2*(1+q)-q)*m+j+dVr)/i
                    if not (0 < p1 < 1.05):
                        continue
                    for n in m1:
                        # q i m n p1
                        p2 = 1-j2*(1+q)+q-(i/m)*(1-j1*(1+n)+n-p1)+dVg/m
                        if not (0 < p2 < 1.05):
                            continue
                        for k in L1:
                            # i j q m p1
                            dVrchk = (q-(j2*q)-q)*m+(p1*i)-j+DR+DB
                            if not (dVr - 100 < dVrchk < dVr + 100):
                                continue
                            # n i k m p2
                            dVlchk =(j1-n+(j1*n))*i+k-(p2*m)
                            if not (dVl - 100 < dVlchk < dVl + 100):
                                continue
                            dVgchk = (1-j1-p1+n-j1*n)*i-(1-j2-p2+q-j2*q)*m
                            # dVgchk is ignored here - Bug?
                            R1init.append(i)
                            R2init.append(j)
                            L1init.append(k)
                            L2init.append(m)
                            p1init.append(p1)
                            p2init.append(p2)
                            m1init.append(n)
                            m2init.append(q)
                            dVrinit.append(dVrchk)
                            dVlinit.append(dVlchk)

    ret = {
        'R1init': R1init,
        'R2init': R2init,
        'L1init': L1init,
        'L2init': L2init,
        'p1init': p1init,
        'p2init': p2init,
        'm1init': m1init,
        'm2init': m2init,
        'dVrinit': dVrinit,
        'dVlinit': dVlinit,
    }
    return ret
def search():
    #converted values to be thousands, assuming this would help with matrix sizes.
    dVl = 194329/1000
    dVr = 51936/1000

    R1 = np.arange(50, 200.001, 2)
    R2 = R1  # Since R1 and R2 are identical
    L1 = -1*R1
    L2 = np.arange(-50,-300.001,-10)

    m1 = np.abs(dVl / R1)
    m2 = np.abs(dVr / L2)

    ret = search_inner(R1, R2, L1, L2, m1, m2)
    # Unwrap typed lists into arrays
    ret = {k: np.array(v, dtype='float64') for k, v in ret.items()}
    return ret
© www.soinside.com 2019 - 2024. All rights reserved.