【问题标题】:Faster method to numerously solve for multiple parameters governed by multiple nonlinear equations with multiple variable arguments?更快的方法来大量求解由具有多个变量参数的多个非线性方程控制的多个参数?
【发布时间】:2021-06-05 18:12:13
【问题描述】:

我正在寻找一种可以应用于稍后显示的代码的调整,或者一种可以加快运行时间的替代方法。一般来说,我想找到由一组多个非线性方程控制的两个参数的值。这些方程使用多个变量参数。

仅以一个小数组(4 个值)为例说明手头的问题:

  • 我想找出由 2 个非线性方程控制的 q 和 h 的值
  • 我需要将此过程应用于较大的 a 和 b 数组,每个数组大约有 50k 个值

等式是:

  • q = k/2L * (h^2 - b^2)
  • q = -2 * pi * k * (h-a) / ln((h-d)/r)

参数/变量:

  • k = 144.0
  • L = 550.0
  • d = 140.9
  • r = 0.5
  • a = [190.0, 185.0, 160.0, 150.0]
  • b = [70.0, 70.0, 30.0, 10.0]

我遵循了 stackoverflow 上类似帖子中的建议,主要是 This post,并修改了我的原始代码以避免使用 for 循环。虽然,在这样做之后,我尝试将代码应用于一大堆变量,但花了相当长的时间。

我还应该提到,我只对 h 在某个限制之间的解决方案感兴趣(当 h 大于 d+r 且小于 300 时),但我不知道如何在 fsolve 中应用它我正在求解多个参数并使用多个非线性函数。

我目前使用的最终代码显示在这篇文章中,但我正在寻找更快、更高效的代码。

import numpy as np

from scipy import optimize

def functions(X, Y):

    q,h = np.split(X,2)

    a,b = np.split(Y[:-4],2)

    k,L = Y[-4],Y[-3]

    d,r = Y[-2],Y[-1]

    f1 = q - k/(2.0*L)*(h**2 - b**2) 

    f2 = q + 2.0*np.pi*k*(h - a)/ np.log((h - d)/r)

    return np.append(f1, f2)

k = 144.0

L = 550.0

d = 140.9

r = 0.5

a_vals = np.array([190.0, 185.0, 160.0, 150.0])

b_vals = np.array([70.0, 70.0, 30.0, 10.0])

q0 = np.array([4059.5, 3814.7, 3212.5, 2912.7]) #initial guesses for q

h0 = np.array([189.5, 184.5, 159.5, 149.5]) #initial guesses for h

my_args = np.concatenate((a_vals, b_vals, k, L, d, r), axis=None)

initial_guesses = np.concatenate((q0, h0), axis=None)

qs,hs = np.split(optimize.fsolve(func = functions, x0 = initial_guesses, args= my_args), 2)

【问题讨论】:

  • 为了找到满足某些界限和约束的特定解决方案,您可以使用类似于this answerscipy.optimize.minimize。您只需要添加一个额外的约束来确保d+r <= 300

标签: python numpy scipy-optimize


【解决方案1】:

在您的情况下,最简单的解决方案是使用 Numba 的 JIT,因为对同一函数执行了许多(短)调用。这是一个例子:

import numba as nb

@nb.njit('float64[::1](float64[::1],float64[::1])')
def functions(X, Y):
    q,h = np.split(X,2)
    a,b = np.split(Y[:-4],2)
    k,L = Y[-4],Y[-3]
    d,r = Y[-2],Y[-1]
    f1 = q - k/(2.0*L)*(h**2 - b**2) 
    f2 = q + 2.0*np.pi*k*(h - a)/ np.log((h - d)/r)
    return np.append(f1, f2)

# ... (the rest is the same)

这在我的机器上快了 12 倍

【讨论】:

  • 首先感谢您的回复和帮助。我尝试了您建议的代码,但收到 TypingError: Failed in nopython mode pipeline (step: nopython frontend) Use of unsupported NumPy function 'numpy.split' or unsupported use of the function。我将 np.split 修改为普通切片,它起作用了,速度提高了大约 9 倍,这要好得多,所以谢谢你。我只是有一个问题,这个装饰方法和@numba.vectorize一样吗?在这种情况下可以使用@numba.vectorize 吗?
  • @yousef 我猜np.split 是由于 Numba 的版本不是最新的。 Numba 0.53.1 对我有用。 AFAIK,@numba.vectorize 不同:它按项目工作(每个项目的计算独立于其他项目)。所以@numba.njit 更通用,因为您可以使用它执行缩减、随机播放等(注意@numba.njit 相当于带有参数nopython=True 的最通用版本@numba.jit)。我不认为@numba.vectorize可以在这种情况下使用。
  • 非常感谢您的澄清
猜你喜欢
  • 2018-07-18
  • 1970-01-01
  • 1970-01-01
  • 2019-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-01-09
  • 2021-10-10
相关资源
最近更新 更多