In my python code, I keep getting the following error:
TypeError: No loop matching the specified signature and casting was found for ufunc svd_n
the code is as follows:
import numpy as np
from numpy.linalg import norm
def sdm_3eqs():
def f_bold(x):
return [15*x[0] x[1]**2 - 4*x[2] - 15, x[0]**2 10*x[1] - x[2] - 10, x[1]**3 - 25*x[2] 24]
def f(x):
f_n = []
for i in range(len(x)):
f_i = f_bold[i]**2
f_n.append(f_i)
return np.sum(f_n)
def M(x):
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
return m
def grad_f(x):
return 2*M(x)*f_bold(x)
def d(x):
return -grad_f(x)/norm(grad_f(x), ord=2)
def s_prime(x, alpha, d):
return grad_f(x alpha*d)*d
x = [0.5, 0.5, 0.5]
iter = 0
err = 100
while err > 0.005:
x_k = x
d_k = d(x_k)
m = 0
sprime = 300
alpha_l = 0
alpha_u = 1.5
alpha = (alpha_l alpha_u)/2
while abs(sprime) > 0.0005:
alpha = (alpha_l alpha_u)/2
sprime = s_prime(x_k, alpha, d_k)[0][0]
if abs(sprime) < 0.001:
break
elif sprime > 0:
alpha_u = alpha
else:
alpha_l = alpha
m = 1
iter = 1
x = x_k alpha*d_k
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
print(f'f_bold: {f_bold(x)}')
sdm_3eqs()
I am unsure why but it says the type error come from line 57 in the code:
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
If anyone can help, that would be great!
EDIT:
Traceback (most recent call last):
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 61, in <module>
sdm_3eqs()
File "/Users/aidanpayne/Desktop/Scripts/Python/University of Greenwich/MATH1157/Scripts/Steepest Descent Method.py", line 57, in sdm_3eqs
err = norm(grad_f(x), ord=2)/max(1, norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2579, in norm
ret = _multi_svd_norm(x, row_axis, col_axis, amax)
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/Users/aidanpayne/opt/anaconda3/lib/python3.8/site-packages/numpy/linalg/linalg.py", line 1673, in svd
s = gufunc(a, signature=signature, extobj=extobj)
TypeError: No loop matching the specified signature and casting was found for ufunc svd_n
CodePudding user response:
It looks like the M(x)
function is returning a 3-dimensional array, of structure
[
[ a [b c d] e ]
[[f g h] i [k l m]]
[ n o p ]
]
and then you're attempting to matrix-multiply that with the result of f_bold(x)
and calculate the norm.
I believe the error is related to trying to calculate the norm of this irregular matrix. In particular, check your function definition for M(x)
to verify the shape/regularity of its returned array.
line 17: m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
^^^^ ^^^^ ^^^^
CodePudding user response:
I added a couple of prints to your code, and got this run:
In [63]: sdm_3eqs()
<ipython-input-62-2b082fcea817>:14: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray.
m = np.array([[15, 2*x[0], 0], [2*x[1], 10, 3*x[1]**2], [-4, -1, -25]])
f_bold
[array([ 6.64610017e-05, -8.57391288e 00, -1.40877199e 01]), array([-3.81306816, -3.03705309, -6.81097338]), array([ 15.47764768, 12.41073581, -18.41883603])]
grad_f
array([[0.0019938300511945783,
array([-36.8081748 , -17.89173085, -17.14782575]), -0.0],
[array([ -8.20903822, -10.93449844, -7.0767119 ]),
-60.74106175194817,
array([-11.83793275, -21.00337307, -8.79740011])],
[-123.82118142652486, -24.821471626766595, 920.9418016830625]],
dtype=object)
Traceback (most recent call last):
File "<ipython-input-63-8732d4079184>", line 1, in <module>
sdm_3eqs()
File "<ipython-input-62-2b082fcea817>", line 57, in sdm_3eqs
err = np.linalg.norm(grad_f(x), ord=2)/max(1, np.linalg.norm(f_bold(x), ord=2))
File "<__array_function__ internals>", line 5, in norm
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2579, in norm
ret = _multi_svd_norm(x, row_axis, col_axis, amax)
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 2355, in _multi_svd_norm
result = op(svd(y, compute_uv=False), axis=-1)
File "<__array_function__ internals>", line 5, in svd
File "/usr/local/lib/python3.8/dist-packages/numpy/linalg/linalg.py", line 1672, in svd
s = gufunc(a, signature=signature, extobj=extobj)
UFuncTypeError: Cannot cast ufunc 'svd_n' input from dtype('O') to dtype('float64') with casting rule 'same_kind'
In new enough numpy versions, the creation of a "ragged array" gets this warning, and tells us that we are not creating a simple numeric array. Instead M
is an object dtype array, containing a mix of numbers and arrays.
f_bold
is a list of arrays. grad_f
is a (3,3) object dtype array with a mix of floats and arrays.
And in the latest numpy version this kind of error specifies the problem dtype - which as I suspected is 'O', object.
norm
cannot handle that kind of array. That's why I asked for the dtype
of the 2 norm
arguments.