Python fsolve () complains about a form. What for?
Having a function f (x, y, z), I need to solve the constraint f (x, y, z) = 0 and then plot it. I tried to find, for each pair (y, z), the x value for which f (x, y, z) = 0:
from numpy import *
from scipy.optimize import fsolve
def func(x,y,z):
return x+y+z
y = linspace(0,1,100)
z = linspace(0,1,100)
x0 = zeros((y.size,z.size)) + 0.5 # the initial guess
yz = (y[:,newaxis],z[newaxis,:]) # the other parameters
x, info, iterations, message = fsolve(func,x0,yz)
contour(y,z,x)
Python (2.7.5) says "TypeError: fsolve: there is a mismatch between the input and output form of the" func "func argument.
But if I test it myself, it gives the same form:
func(x0,y[:,newaxis],z[:,newaxis]).shape == x0.shape
returns True.
Why is fsolve () complaining?
source to share
fsolve
expects the argument x
and return value to func
be scalar or one-dimensional. You will have to modify your code to work with flattened values x
. For example.
def func(x, y, z):
x = x.reshape(y.size, z.size)
return (x + y + z).ravel()
and something like this to call fsolve
:
sol, info, ier, mesg = fsolve(func, x0.ravel(), args=yz, full_output=True) x = sol.reshape(y.size, z.size)
source to share
Here's a comparison to the method krylov
described in the scipy.optimize tutorial :
from numpy import linspace, zeros, newaxis
import time
from scipy.optimize import root
def func(x,y,z):
x = x.reshape(y.size, z.size)
f = x + y + z
f = f.ravel()
return f
n = 50
y = linspace(0,1,n)
z = linspace(0,1,n)
x0 = zeros((y.size,z.size)) + 0.5 # the initial guess
yz = (y[:,newaxis],z[newaxis,:]) # the other parameters
start = time.time()
sol1 = root(func, x0.ravel(), args=yz, method='hybr', tol=1e-7) # same as fsolve
x1 = sol1.x.reshape(y.size, z.size)
print("(fsolve) time taken (sec): %g" % (time.time() - start,))
print("(fsolve) successful: %r (%s)" % (sol1.success, sol1.message))
print("(fsolve) max error: %g" % (abs(func(x1, *yz)).max(),))
start = time.time()
sol2 = root(func, x0.ravel(), args=yz, method='krylov', tol=1e-9)
x2 = sol2.x.reshape(y.size, z.size)
print("(krylov) time taken (sec): %g" % (time.time() - start,))
print("(krylov) successful: %r (%s)" % (sol2.success, sol2.message))
print("(krylov) max error: %g" % (abs(func(x2, *yz)).max(),))
Printing
(fsolve) time taken (sec): 26.9296 (fsolve) successful: False (The iteration is not making good progress, as measured by the improvement from the last ten iterations.) (fsolve) max error: 1.52656e-16 (krylov) time taken (sec): 0.0173709 (krylov) successful: True (A solution was found at the specified tolerance.) (krylov) max error: 1.11022e-16
source to share