Python中的多变量线性化:'Pow'对象没有'sqrt'属性。

7
作为Python世界的新手,我只需要将以下两个变量函数线性化:
函数

enter image description here

使用相当常见的牛顿法进行计算:
线性化方法

enter image description here

这是我到目前为止尝试过的:

import numpy as np
import math
from sympy import symbols, diff

d = 1.7

def f(arg1, arg2):
    return (arg1 - arg2)/(np.power(np.linalg.norm(arg1 - arg2),2) - np.power(d,2))

def linearize_f(f, arg1, arg2, equi_arg1, equi_arg2):
    arg1, arg2 = symbols('arg1 arg2', real=True)
    der_1 = diff(f(arg1,arg2), arg1)
    der_2 = diff(f(arg1,arg2), arg2)
    constant_term = f(equi_arg1, equi_arg2)

    vars = sympy.symbols('arg1, arg2')
    par_term_1 = sympy.evalf(der_1, subs = dict(zip(vars,[equi_arg1, equi_arg2])))
    par_term_2 = sympy.evalf(der_2, subs = dict(zip(vars,[equi_arg1, equi_arg2])))

    result = constant_term + par_term_1*(arg1-equi_arg1) + par_term_2*(arg2-equi_arg2)

    return result

q0, q1 = symbols('q0 q1', real=True)
result = linearize_f(f,q0,q1,0,0)
print(result)

解释器返回一个 'Pow' object has no attribute 'sqrt'。然而,我在我的代码中从未使用过任何 sqrt
请帮我解决这个问题。

已验证。如果arg1arg2都是数字,则似乎正常工作;当它们是符号时,出现相同的错误。 - Rocky Li
我可以问一下 arg1arg2 是什么吗?它们是数组还是单个数字? - Rocky Li
@RockyLi:这些参数是“点”。换句话说,每个参数都是包含两个元素的列表,就像 xy - user10696076
公式的图片似乎与问题无关。只要代码足以重现错误,源公式实际上是什么并不重要。强迫读者去解密手写内容有点浪费时间,而且这并不是必要的。除此之外,问题很好。 - BartoszKP
sympy 对象传递给 numpy 函数通常不起作用。由于该函数旨在与 ndarray 协同工作,因此 numpy 执行 np.asarray(arg)。这很可能会产生一个 object dtype 数组。np.sqrt(obj_array) 尝试为数组的每个元素执行 x.sqrt()。如果元素恰好具有该方法,则可以正常工作;否则就会出现错误。 - hpaulj
为了在这段 sympy 代码中有用,你的 f 必须写成一个 sympy 函数,不能使用任何 numpy - hpaulj
2个回答

3
您尚未调用sqrt函数,但已调用np.linalg.norm函数。参数arg1, arg2的类型为sympy.Symbol。该函数期望得到一个类似于数组的参数,但它得到了一个sympy符号,而不知道如何处理。
我查看了np.linalg源代码,似乎它检查了一些已知类型并尝试找到平方根。否则,它依赖于参数本身来知道其自己的平方根。但是,sympy.Symbol并没有这个功能,因此会出现错误。
无法避免这种情况。 numpy使用数字,而sympy使用(自己的)符号。您不应混合使用它们。最有可能sympy将具有处理其自己符号的函数,但如果没有,除非您自己添加,否则无法实现。

2

我已经将你的错误缩小到这个:

q0, q1 = symbols('q0 q1', real=True)
np.linalg.norm(q0 - q1) # Throws the same error

这是在np.linalg中引发错误的源代码:

2347 
2348     # Immediately handle some default, simple, fast, and common cases.
2349     if axis is None:
2350         ndim = x.ndim
2351         if ((ord is None) or
2352             (ord in ('f', 'fro') and ndim == 2) or
2353             (ord == 2 and ndim == 1)):
2354 
2355             x = x.ravel(order='K')
2356             if isComplexType(x.dtype.type):
2357                 sqnorm = dot(x.real, x.real) + dot(x.imag, x.imag)
2358             else:
2359                 sqnorm = dot(x, x)
2360             ret = sqrt(sqnorm)
2361             if keepdims:
2362                 ret = ret.reshape(ndim*[1])
2363             return ret

显然,在您的sympy对象经过“dot”处理后,它变成了一个“Pow”对象,这是一个sympy对象,而“np.sqrt”不知道如何处理。
这个显然的原因是,您不能使用numpy函数来处理sympy对象。“Pow”是一个sympy对象,因此“numpy.sqrt”无法对该对象进行操作。
经过更多的研究,显然,很久以前的这个问题sympy AttributeError: 'Pow' object has no attribute 'sin'也指向了同样的原因。

1
感谢您找出问题的源头,但您能否准确地解释一下我该如何解决这个问题呢?肯定有方法可以解决这个问题,对吧?! - user10696076
你可以尝试使用 sympy 函数,例如 (args1-args2).norm(),而不是使用 np.linalg.norm。根据文档,norm 是一个 sympy 函数,你可能还需要将 np.power 更改为 sympy.core.power - Rocky Li
这样做会导致出现“'add' object has no attribute norm”的错误,我认为这意味着sympy甚至不知道操作(args1-args2)!https://docs.sympy.org/0.7.2/modules/matrices/matrices.html - user10696076
另一个 sympy/numpy 的链接:https://stackoverflow.com/questions/52619874/sympy-numpy-integration-exists-where-is-it-documented - hpaulj

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接