更快地求解由具有多个变量参数的多个非线性方程控制的多个参数的方法?
Faster method to numerously solve for multiple parameters governed by multiple nonlinear equations with multiple variable arguments?
我正在寻找可以应用于稍后显示的代码的调整,或者可以缩短 运行 时间的替代方法。通常,我想找到由一组多个非线性方程控制的两个参数的值。这些等式使用多个变量参数。
手头问题的示例仅以一个小数组(4 个值)为例:
- 我想找出由 2 个非线性方程控制的 q 和 h 的值
- 我需要将此过程应用于较大的 a 和 b 数组,每个数组大约有 50k 个值
等式为:
- q = k/2L * (h^2 - b^2)
- q = -2 * pi * k * (h-a) / ln((h-d)/r)
arguments/variables:
- 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]
我遵循了 Whosebug 上类似 post 中的建议,主要是 ,并修改了我的原始代码以避免使用 for 循环。虽然在这样做之后,我尝试将代码应用于大量变量,但它花费了相当长的时间。
我还应该提到,我只对 h 在某个限制之间(当 h 大于 d+r 且小于 300)时的解决方案感兴趣,但我不知道如何将其应用到fsolve 当我求解多个参数并使用多个非线性函数时。
我目前使用的最终代码显示在此 post,但我正在寻找更快、更高效的代码。
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)
在您的情况下,最简单的解决方案是使用 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 倍。
我正在寻找可以应用于稍后显示的代码的调整,或者可以缩短 运行 时间的替代方法。通常,我想找到由一组多个非线性方程控制的两个参数的值。这些等式使用多个变量参数。
手头问题的示例仅以一个小数组(4 个值)为例:
- 我想找出由 2 个非线性方程控制的 q 和 h 的值
- 我需要将此过程应用于较大的 a 和 b 数组,每个数组大约有 50k 个值
等式为:
- q = k/2L * (h^2 - b^2)
- q = -2 * pi * k * (h-a) / ln((h-d)/r)
arguments/variables:
- 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]
我遵循了 Whosebug 上类似 post 中的建议,主要是
我还应该提到,我只对 h 在某个限制之间(当 h 大于 d+r 且小于 300)时的解决方案感兴趣,但我不知道如何将其应用到fsolve 当我求解多个参数并使用多个非线性函数时。
我目前使用的最终代码显示在此 post,但我正在寻找更快、更高效的代码。
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)
在您的情况下,最简单的解决方案是使用 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 倍。