user10696076
user10696076

Reputation:

multivariable linearization in python: 'Pow' object has no attribute 'sqrt'

As a newcomer to Python world, I'm just simply about to linearize the following two variable function:

function

enter image description here

using the fairly routine Newton method:

linearization method

enter image description here

Here is what I've tried so far:

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)

The interpreter returns a 'Pow' object has no attribute 'sqrt'. However, I've never used any sqrt in my code.

Would you please help me to resolve the case?

Upvotes: 7

Views: 1418

Answers (2)

Rocky Li
Rocky Li

Reputation: 5958

I've narrowed your error to this:

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

Here's the source code in np.linalg where it threw the error:

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

Apparently, after your sympy object has been processed by dot, it became a Pow object, which is a sympy object that np.sqrt has no idea what to do with.

The reason for this apparently is that you cannot use numpy function for sympy objects. Pow is a sympy object and as such numpy.sqrt cannot operate on this object.

After more reasearch, apparently this question from long time ago sympy AttributeError: 'Pow' object has no attribute 'sin' also point to the same reason.

Upvotes: 2

blue note
blue note

Reputation: 29081

You have not called sqrt but np.linalg.norm has. The arg1, arg2 arguments are of type sympy.Symbol. The function expects to get an array-like argument. However, it gets a sympy symbol, which it does not know how to handle.

I looked in the np.linalg source code, and it seems that it checks for some known types and tries to find the square root. Otherwise, it relies on the argument itself to know its own square root. sympy.Symbol has no such thing, and hence the error.

There is no way to avoid this. numpy works with numbers, sympy works with (its own) symbols. You are not supposed to mix them. Most likely sympy will have its own functions for handling its own symbols, but, if not, you are out of luck, unless you add them yourself.

Upvotes: 3

Related Questions