I seem to be getting an error when I use the root-finder in scipy. I was wondering if anyone could point out what I'm doing wrong.
The function I'm finding the root of is just an easy example, and not particularly important.
If I run this code with scipy 0.9.0:
import numpy as np
from scipy.optimize import fsolve
tmpFunc = lambda xIn: (xIn[0]-4)**2 + (xIn[1]-5)**2 + (xIn[2]-7)**3
x0 = [3,4,5]
xFinal = fsolve(tmpFunc, x0 )
print xFinal
I get the following error message:
Traceback (most recent call last):
File "tmpStack.py", line 7, in <module>
xFinal = fsolve(tmpFunc, x0 )
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 115, in fsolve
_check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/usr/lib/python2.7/dist-packages/scipy/optimize/minpack.py", line 26, in _check_func
raise TypeError(msg)
TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument '<lambda>'.
Well it looks like I was trying to use this routine incorrectly. This routine requires the same number of equations and variables vs. the one equation with three variables I gave it. So if the input to the function to be minimized is a 3-D array the output should be a 3-D array. This code works:
import numpy as np
from scipy.optimize import fsolve
tmpFunc = lambda xIn: np.array( [(xIn[0]-4)**2 + xIn[1], (xIn[1]-5)**2 - xIn[2]) \
, (xIn[2]-7)**3 + xIn[0] ] )
x0 = [3,4,5]
xFinal = fsolve(tmpFunc, x0 )
print xFinal
Which represents solving three equations simultaneously.
Related
I know there are plenty of subject on this error and I've been on many of them trying to understand what is going on with sush a simple system. Here is my code, solving a very simple equation to test the efficiency of solve_ivp vs odeint.
import numpy as np
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import solve_ivp
def fun(t,x,a) :
return -x/a
t = np.linspace(0,10,1000)
tspan = [t[0], t[-1]]
x0 = [10]
sol = solve_ivp(fun, tspan, x0, t_eval = t, args = 1)
plt.plot(t,sol.y.T)
plt.show()
And this is the full error report :
/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/common.py:40:
/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/common.py:40:
UserWarning: The following arguments have no effect for a chosen solver: `args`.
warn("The following arguments have no effect for a chosen solver: {}."
Traceback (most recent call last):
File "test.py", line 25, in <module>
sol = solve_ivp(fun, tspan, x0, t_eval = t, args = 1)
File "/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/ivp.py", line
477, in solve_ivp
solver = method(fun, t0, y0, tf, vectorized=vectorized, **options)
File "/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/rk.py", line
100, in __init__
self.f = self.fun(self.t, self.y)
File "/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/base.py", line
139, in fun
return self.fun_single(t, y)
File "/home/anthony/.local/lib/python3.8/site-packages/scipy/integrate/_ivp/base.py", line
21, in fun_wrapped
return np.asarray(fun(t, y), dtype=dtype)
TypeError: fun() missing 1 required positional argument: 'a'
To me, the error is pretty clear but it is also very obvious that I put in the right place my argument according to the documentation of this solver doc scipy.integrate.solve_ivp
I also upgraded to the latest my scipy version, any advices would be very helful.
args is supposed to be a tuple
In [281]: sol = solve_ivp(fun, tspan, x0, t_eval = t, args = (1,))
In [282]: sol
Out[282]:
message: 'The solver successfully reached the end of the integration interval.'
nfev: 80
njev: 0
nlu: 0
sol: None
status: 0
success: True
....
Messing up the args is one of the most common scipy.integrate (and optimize) SO errors.
I am fitting a very simple curve having three points. with leastsq method, following all the rules. But still I am getting error. I cannot understand. Can anyone help. Thank you so much
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
x = np.array([2.0,30.2,15.0])
y = np.array([45.0,56.2,30.0])
print(x)
print(y)
# model
def t(x,a,b,c):
return a*x**2 + b*x + c
#residual fucntion
def residual_t(x,y,a,b,c):
return y-t(x,a,b,c)
#initial parameters
g0 = np.array([0.0,0.0,0.0])
#leastsq method
coeffs, cov = leastsq(residual_t, g0, args=(x,y))
plt.plot(x,t(x,*coeffs),'r')
plt.plot(x,y,'b')
plt.show()
#finding out Rsquared and Radj squared value
absError = residual_t(y,x,*coeffs)
se = np.square(absError) # squared errors
Rsquared = 1.0 - (np.var(absError) / np.var(y))
n = len(x)
k = len(coeffs)
Radj_sq = (1-((1-Rsquared)/(n-1)))/(n-k-1)
print (f'Rsquared value: {Rsquared} adjusted R saquared value: {Radj_sq}')
TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'
Why??
coeffs is already a array containing best it values of a, b,c. coeffs is also showing undefined and residual_t is also showing problem. Could you please help me to understand.
With a copy-n-paste of your code (including the *coeffs change), I get
1135:~/mypy$ python3 stack58206395.py
[ 2. 30.2 15. ]
[45. 56.2 30. ]
Traceback (most recent call last):
File "stack58206395.py", line 24, in <module>
coeffs, cov = leastsq(residual_t, g0, args=(x,y))
File "/usr/local/lib/python3.6/dist-packages/scipy/optimize/minpack.py", line 383, in leastsq
shape, dtype = _check_func('leastsq', 'func', func, x0, args, n)
File "/usr/local/lib/python3.6/dist-packages/scipy/optimize/minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'
That is the error is in the use of residual_t within the leastsq call.
If I add
residual_t(g0, x, y)
right after the g0 definition I get the same error:
1136:~/mypy$ python3 stack58206395.py
[ 2. 30.2 15. ]
[45. 56.2 30. ]
Traceback (most recent call last):
File "stack58206395.py", line 23, in <module>
residual_t(g0, x, y)
TypeError: residual_t() missing 2 required positional arguments: 'b' and 'c'
So you need to define residual_t to work with a call like this. I'm not going to take a guess as to what you really want, so I'll leave the fix up to you.
Just remember that residual_t will be called with the x0, spliced with the args tuple. This is typical usage for scipy.optimize functions. Review the docs if necessary.
edit
Defining the function as:
def residual_t(abc, x, y):
a,b,c = abc
return y-t(x,a,b,c)
runs without error.
import math
from scipy.optimize import fsolve
def sigma(s, Bpu):
return s - math.sin(s) - math.pi * Bpu
def jac_sigma(s):
return 1 - math.cos(s)
if __name__ == '__main__':
Bpu = 0.5
sig_r = fsolve(sigma, x0=[math.pi], args=(Bpu), fprime=jac_sigma)
Running the above script throws the following error,
Traceback (most recent call last):
File "C:\Users\RP12808\Desktop\_test_fsolve.py", line 12, in <module>
sig_r = fsolve(sigma, x0=[math.pi], args=(Bpu), fprime=jac_sigma)
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 146, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 226, in _root_hybr
_check_func('fsolve', 'fprime', Dfun, x0, args, n, (n, n))
File "C:\Users\RP12808\AppData\Local\Programs\Python\Python36\lib\site-packages\scipy\optimize\minpack.py", line 26, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: jac_sigma() takes 1 positional argument but 2 were given
I am unsure how to pass jacobian to fsolve function... how do solve this?
Thanks in advance..RP
The function that computes the Jacobian matrix must take the same arguments as the function to be solved, and it must return an array:
def jac_sigma(s, Bpu):
return np.array([1 - math.cos(s)])
In general, the Jacobian matrix is a two-dimensional array, but
when the variable is a scalar (as it is here) and the Jacobian "matrix" is 1x1, the code accepts a one- or two-dimensional value. (It might be nice if it also accepted a scalar in this case, but it doesn't.)
Actually, it is sufficient that the return value be "array-like"; e.g. a list is also acceptable:
def jac_sigma(s, Bpu):
return [1 - math.cos(s)]
I have an issu when i'm trying to minimize my (complex matrix) function using fsolve or scipy.optimize.newton but both of them didn't worked. Indeed, my function is 2*2 matrix with complex value. First, I defined my function in a Class i called real() and it is called by my main program MAin.py:
import sys,os
import numpy as np
import random, math
from scipy.optimize import fsolve
from scipy import optimize
class real :
def __init__(self):
self.w = 2
def func1(self,eps):
self.k_ch=2.5*np.exp(eps)
f=np.array([[0,eps*3*self.k_ch+0.032],[0,self.w]])
return f
And my Main program is:
import sys,os
import numpy as np
import random, math, cmath
from scipy.optimize import fsolve
from Carlo import *
A=real()
eps=0.003+0.0042j
C=A.func1(eps)
Cp=0
track=1e-03
variable=np.arange(track,0.1,1)
for track in variable:
Cp=Cp+1
if Cp==1:
eps_real=0
elif Cp==1:
fray=np.array([Cp-1,2])
eps_real=fray/2*3.14*track
R_0= fsolve(C,eps.real)
print R_0
if xtol<=1e-04:
value_stock= np.array([Cp-1,2])
print 'R_0 value is', R_0
But I got this error:
Traceback (most recent call last):
File "Main.py", line 29, in <module>
R_0= fsolve(C,eps.real)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 127, in fsolve
res = _root_hybr(func, x0, args, jac=fprime, **options)
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 183, in _root_hybr
_check_func('fsolve', 'func', func, x0, args, n, (n,))
File "/System/Library/Frameworks/Python.framework/Versions/2.7/Extras/lib/python/scipy/optimize/minpack.py", line 14, in _check_func
res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))
TypeError: 'numpy.ndarray' object is not callable
Since i'm a new beginner with python, I don't know how to deal with it. Can you help me please if you have any idea. It seems like maybe fsolve does not like complex value but I got the same error using scipy.optimize.newton.
Thank you.
fsolve needs a function in the first argument. You provided C which is a numpy.ndarray, not a function.
I wonder why you use fsolve while you state you want to minimize a function? In case minimization is what you want, this example straight from the scipy.optimize tutorial might set you on track:
import numpy as np
from scipy.optimize import minimize
def rosen(x):
"""The Rosenbrock function"""
return sum(100.0*(x[1:]-x[:-1]**2.0)**2.0 + (1-x[:-1])**2.0)
x0 = np.array([1.3, 0.7, 0.8, 1.9, 1.2])
res = minimize(rosen, x0, method='nelder-mead',
options={'xtol': 1e-8, 'disp': True})
print(res.x)
[ 1. 1. 1. 1. 1.]
I often have to solve nonlinear problems in which the number of variables exceeds the number of constraints (or sometimes the other way around). Usually some of the constraints or variables are redundant in a complicated way. Is there any way to solve such problems?
Most of the scipy solvers seem to assume that the number of constraints equals the number of variables, and that the Jacobian is nonsingular. leastsq works sometimes but it doesn't even try when the constraints are fewer than the number of variables. I realize that I could just run fmin on linalg.norm(F), but this is much less efficient than any method which makes use of the Jacobian.
Here is an example of a problem which demonstrates what I am talking about. It obviously has a solution, but leastsq gives an error. Of course, this example is easy to solve by hand, I just put it here to demonstrate the issue.
import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
y = np.dot(mat, x)
return np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17 ])
x0 = np.random.randn(7)
scipy.optimize.leastsq(F, x0)
The error message I get is:
Traceback (most recent call last):
File "question.py", line 13, in <module>
scipy.optimize.leastsq(F, x0)
File "/home/dstahlke/apps/scipy/lib64/python2.7/site-packages/scipy/optimize/minpack.py", line 278, in leastsq
raise TypeError('Improper input: N=%s must not exceed M=%s' % (n,m))
TypeError: Improper input: N=7 must not exceed M=2
I have scoured the net for an answer and have even asked on the SciPy mailing list, and got no response. For now I hacked the SciPy source so that the newton_krylov solver uses pinv(), but I don't think this is an optimal solution.
How about resize the return array from F() to the number of variables:
import numpy as np
import scipy.optimize
mat = np.random.randn(5, 7)
def F(x):
y = np.dot(mat, x)
return np.resize(np.array([ y[0]**2 + y[1]**3 + 12, y[2] + 17]), 7)
while True:
x0 = np.random.randn(7)
r = scipy.optimize.leastsq(F, x0)
err = F(r[0])
norm = np.dot(err, err)
if norm < 1e-6:
break
print err