【问题标题】:Efficient way to calculate where a multivariable function takes values between a interval in Python计算多变量函数在Python中的区间之间取值的有效方法
【发布时间】:2018-04-17 15:49:42
【问题描述】:

我有两个确定机器人逆运动学的多元方程。这些方程取决于变量 theta1 和 theta2(其他变量是几何常数)

import numpy as np

def x(theta1, theta2, w, h, L1, L2):
    sint1 = np.sin(theta1)
    cost1 = np.cos(theta1)
    sint2 = np.sin(theta2)
    cost2 = np.cos(theta2)

    i1 = L1 * (cost1 + cost2) + w
    j1 = L1 * (sint1 - sint2) - h
    D = np.sqrt((L1*(cost2-cost1)+w)**2+(L1*(sint2-sint1)+h)**2)
    a = (0.25)*np.sqrt((4*L2**2-D**2)*D**2)

    return i1/2 + 2*j1*a/(D**2)

def y(theta1, theta2, w, h, L1, L2):
    sint1 = np.sin(theta1)
    cost1 = np.cos(theta1)
    sint2 = np.sin(theta2)
    cost2 = np.cos(theta2)

    i2 = L1 * (sint1 + sint2) + h
    j2 = L1 * (cost1 - cost2) - w
    D = np.sqrt((L1*(cost2-cost1)+w)**2+(L1*(sint2-sint1)+h)**2)
    a = (0.25)*np.sqrt((4*L2**2-D**2)*D**2)

    return i2/2 - 2*j2*a/(D**2)

使用这些方程,我使用二阶有限差分法计算雅可比矩阵(偏导数矩阵)的行列式

def det_jacobian(theta1, theta2, w, h, L1, L2,eps):
    dxdt1 = (-x(theta1+eps, theta2, w, h, L1, L2)+4*x(theta1, theta2, w, h, L1, L2)-3*x(theta1-eps, theta2, w, h, L1, L2))/(2*eps)
    dxdt2 = (-x(theta1, theta2+eps, w, h, L1, L2)+4*x(theta1, theta2, w, h, L1, L2)-3*x(theta1, theta2-eps, w, h, L1, L2))/(2*eps)
    dydt1 = (-y(theta1+eps, theta2, w, h, L1, L2)+4*y(theta1, theta2, w, h, L1, L2)-3*y(theta1-eps, theta2, w, h, L1, L2))/(2*eps)
    dydt2 = (-y(theta1, theta2+eps, w, h, L1, L2)+4*y(theta1, theta2, w, h, L1, L2)-3*y(theta1, theta2-eps, w, h, L1, L2))/(2*eps)  
    return dxdt1,dxdt2,dydt1,dydt2

针对属于某个区间的 theta1 和 theta2 的值进行评估

theta1 = np.linspace(theta1_min,theta1_max,n)
theta2 = np.linspace(theta2_min,theta2_max,n)
theta1, theta2 = np.meshgrid(theta1,theta2)

我想知道是否有一种有效的方法(使用 numpy 数组)来计算 x 和 y 的值,其中行列式的值介于 -tol 和 tol 之间(tol=1e-08)。目前我正在使用两个嵌套的for循环,但速度很慢

我用for循环写了一个函数,但是很慢

def singularidades(theta1_min,theta1_max, theta2_min,theta2_max, n,tol, w, h, L1, L2,eps):
    x_s = []
    y_s = []
    theta1_s = []
    theta2_s = []
    det = []
    theta1 = np.linspace(theta1_min,theta1_max,n)
    theta2 = np.linspace(theta2_min,theta2_max,n)
    theta1, theta2 = np.meshgrid(theta1,theta2)
    det_jac = det_jacobiano(theta1,theta2,w,h,L1,L2,eps)
    for i in range(n):
        for j in range(n):
            if (g_tol[i,j] and l_tol[i,j]):
                x_s.append(x(theta1[i,j], theta2[i,j], w, h, L1, L2))
                y_s.append(y(theta1[i,j], theta2[i,j], w, h, L1, L2))
                theta1_s.append(theta1[i,j])
                theta2_s.append(theta2[i,j])
                det.append(det_jac[i,j])
   return x_s,y_s,theta1_s,theta2_s,det,(g_tol and l_tol)

编辑:我已修改 det_jacobian 函数以将其与 scipy.optimize.root 一起使用

def det_jacobiano(theta, w, h, L1, L2,eps):
    theta1,theta2 = theta
    dxdt1 = (-x(theta1+eps, theta2, w, h, L1, L2)+4*x(theta1, theta2, w, h, L1, L2)-3*x(theta1-eps, theta2, w, h, L1, L2))/(2*eps)
    dxdt2 = (-x(theta1, theta2+eps, w, h, L1, L2)+4*x(theta1, theta2, w, h, L1, L2)-3*x(theta1, theta2-eps, w, h, L1, L2))/(2*eps)
    dydt1 = (-y(theta1+eps, theta2, w, h, L1, L2)+4*y(theta1, theta2, w, h, L1, L2)-3*y(theta1-eps, theta2, w, h, L1, L2))/(2*eps)
    dydt2 = (-y(theta1, theta2+eps, w, h, L1, L2)+4*y(theta1, theta2, w, h, L1, L2)-3*y(theta1, theta2-eps, w, h, L1, L2))/(2*eps)  
    return dxdt1*dydt2 - dxdt2*dydt1

我正在尝试使用

initial_guess = [2.693, 0.4538]
result = optimize.root(det_jacobiano, initial_guess,tol=1e-8,args=(20,0,100,100,1e-10),method='lm')

但我得到了错误:

TypeError: Improper input: N=2 must not exceed M=1

【问题讨论】:

  • 按照我阅读问题的方式,OP 希望以某种方式从给定的间隔限制自动生成 xy 值,从而产生二维结果数组。这需要在每个方向上添加某种步进参数。
  • 已更新。非常感谢您的帮助
  • 请看你的帖子:你给了我们大约 30 行计算代码,然后问了一个关于你包含和不包含的代码的问题 其有效性取决于计算。
  • 也许我解释错了。我为此道歉,因为英语不是我的母语。目前我有完美运行的函数 det_jacobian。我想要的是在一个范围(0,np.pi)内评估 det_jacobian 的不同值,如果 det_jacobian 在 -1e-8 和 1e-8 之间,则将值 x 和 y 放在列表或数组中。
  • 请发布您希望我们改进的代码。对于您描述的问题,您可以将该代码替换为名为 complex_computation 的代码,该代码以所需格式返回随机值。

标签: python algorithm numpy math numeric


【解决方案1】:

您不需要循环。您的函数可以使用 numpy 数组以及单个值:

def f(x,y):
    return np.sin(x + y) / np.sqrt(x**2 + y**2)

x = [0.1, 0.2, 0.3, 0.4, 0.5]
y = [0.1, 0.2, 0.3, 0.4, 0.5]

print(f(x, y))

将返回:

[1.40480431, 1.37680175, 1.33087507, 1.26811839, 1.19001968]

它是每对 x 和 y 的函数值数组

【讨论】:

  • 我认为我们对这个问题的理解完全不同。我不确定哪种解释是正确的......
  • 是的,这令人困惑。再次查看问题后,您的方法也很有意义。我认为作者需要更深入地解释他的问题。
  • 已更新。非常感谢您的帮助
【解决方案2】:

一种方法是定义:

def f(x,y,a):
    return np.sin(x + y) / np.sqrt(x**2 + y**2) - a

其中a 可以获取区间的限制,然后使用scipy.optimize 计算此函数的根x0y0

这些根对应于函数的 xy 值,函数在这两个值之间返回所需的值。

【讨论】:

  • 已更新。非常感谢您的帮助
  • 如果我正确理解您的编辑,我认为您应该能够计算 det_jacobiano - g_tol 的根和 det_jacobiano - l_tol 的根,以便根代表 theta1theta2 在函数进入和离开您想要的公差范围。我将更新我的答案以说明这一点。如果我理解正确,请告诉我。
  • 是的。没有一个根,它们是一组根。谢谢你。我试图问一个更笼统的问题,但结果很模糊
  • scipy.optimize 也应该适用于多维函数。我认为它应该比当前的循环方法更有效。
  • 我去看看。谢谢。
猜你喜欢
  • 2014-12-17
  • 2018-07-18
  • 1970-01-01
  • 2021-11-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-16
  • 2021-12-13
相关资源
最近更新 更多