Before I go into my problem, I've searched the relevant threads on stackoverflow with the same problem:
From what I understand reading about this error,
raise TypeError(msg)
TypeError: fsolve: there is a mismatch between the input and output shape of the 'func' argument 'fsolve_function'
The issue is that the shape of the input and output are not the same.
In my code example below, I have the following:
initialGuess
(the starting estimate to be used in the fsolve
function in scipy.optimize). The input, initialGuess
has 3 starting estimates for coordinates x,y and z. Therefore I expect my starting input estimate to have always three inputs.out
(non-linear simultaneous equations). In this example I have 4 non-linear equations.scipy.optimize.fsolve
raises the error highlighted above, because the input and output do not have the same shape. In my particular case, I want my input to always have three values (to guess the initial starting points of x, y, and z). The output in this case has 4 non-linear equations to solve using the initial input estimate.fsolve
will do the calculation accordingly. I'm just wondering how could you extend fsolve
to use let's say equal or more than 4 non-linear simultaneous equations with just 3 input initial estimates?Code below:
from scipy.optimize import fsolve
def fsolve_function(arguments):
x = arguments[0]
y = arguments[1]
z = arguments[2]
out = [(35.85 - x)**2 + (93.23 - y)**2 + (-39.50 - z)**2 - 15**2]
out.append((42.1 - x)**2 + (81.68 - y)**2 + (-14.64 - z)**2 - 27**2)
out.append((-70.90 - x)**2 + (-55.94 - y)**2 + (-68.62 - z)**2 - 170**2)
out.append((-118.69 - x)**2 + (-159.80 - y)**2 + (-39.29 - z)**2 - 277**2)
return out
initialGuess = [35, 93, -39]
result = fsolve(fsolve_function, initialGuess)
print result
fsolve
is a wrapper of MINPACK's hybrd
, which requires the function's argument and output have the same number of elements. You can try other algorithms from the more general scipy.optimize.root
that do not have this restriction (e.g. lm
):
from scipy.optimize import fsolve, root
def fsolve_function(arguments):
x = arguments[0]
y = arguments[1]
z = arguments[2]
out = [(35.85 - x)**2 + (93.23 - y)**2 + (-39.50 - z)**2 - 15**2]
out.append((42.1 - x)**2 + (81.68 - y)**2 + (-14.64 - z)**2 - 27**2)
out.append((-70.90 - x)**2 + (-55.94 - y)**2 + (-68.62 - z)**2 - 170**2)
out.append((-118.69 - x)**2 + (-159.80 - y)**2 + (-39.29 - z)**2 - 277**2)
return out
initialGuess = [35, 93, -39]
result = root(fsolve_function, initialGuess, method='lm')
print(result.x)
Incidentally, it cannot find the actual zero --- is there supposed to be one at all?
You can also force fsolve
to use your function if you supply it an initial guess with a "bogus" fourth variable:
initialGuess = [35, 93, -39, 0]
but I'm not sure how reliable are the results in this case.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With