简体   繁体   中英

Python fsolve ValueError

Why does the following code return a ValueError?

from scipy.optimize import fsolve
import numpy as np

def f(p,a=0):
    x,y = p
    return (np.dot(x,y)-a,np.outer(x,y)-np.ones((3,3)),x+y-np.array([1,2,3]))

x,y = fsolve(f,(np.ones(3),np.ones(3)),9)


ValueError: setting an array element with a sequence.

The basic problem here is that your function f does not satisfy the criteria required for fsolve to work. These criteria are described in the documentation - although arguably not very clearly.

The particular things that you need to be aware of are:

  1. the input to the function that will be solved for must be an n-dimensional vector (referred to in the docs as ndarray ), such that the value of x you want is the solution to f(x, *args) = 0 .
  2. the output of f must be the same shape as the x input to f .

Currently, your function takes a 2 member tuple of 1x3-arrays (in p ) and a fixed scalar offset (in a ). It returns a 3 member tuple of types ( scalar , 3x3 array , 1x3 array )

As you can see, neither condition 1 nor 2 is met.

It is hard to advise you on exactly how to fix this without being exactly sure of the equation you are trying to solve. It seems you are trying to solve some particular equation f(x,y,a) = 0 for x and y with x0 = (1,1,1) and y0 = (1,1,1) and a = 9 as a fixed value. You might be able to do this by passing in x and y concatenated (eg pass in p0 = (1,1,1,1,1,1) and in the function use x=p[:3] and y = p[3:] but then you must modify your function to output x and y concatenated into a 6-dimensional vector similarly. This depends on the exact function your are solving for and I can't work this out from the output of your existing f (ie based on a dot product, outer product and sum based tuple).

Note that arguments that you don't pass in the vector (eg a in your case) will be treated as fixed values and won't be varied as part of the optimisation or returned as part of any solution.


Note for those who like the full story...

As the docs say:

fsolve is a wrapper around MINPACK's hybrd and hybrj algorithms.

If we look at the MINPACK hybrd documentation , the conditions for the input and output vectors are more clearly stated. See the relevant bits below (I've cut some stuff out for clarity - indicated with ... - and added the comment to show that the input and output must be the same shape - indicated with <--)

1 Purpose.

The purpose of HYBRD is to find a zero of a system of N non- linear functions in N variables by a modification of the Powell hybrid method. The user must provide a subroutine which calcu- lates the functions. The Jacobian is then calculated by a for- ward-difference approximation.

2 Subroutine and type statements.

  SUBROUTINE HYBRD(FCN,N,X, ... 

...

FCN is the name of the user-supplied subroutine which calculates the functions. FCN must be declared in an EXTERNAL statement in the user calling program, and should be written as follows.

  SUBROUTINE FCN(N,X,FVEC,IFLAG) INTEGER N,IFLAG DOUBLE PRECISION X(N),FVEC(N) <-- input X is an array length N, so is output FVEC ---------- CALCULATE THE FUNCTIONS AT X AND RETURN THIS VECTOR IN FVEC. ---------- RETURN END 

N is a positive integer input variable set to the number of functions and variables.

X is an array of length N. On input X must contain an initial estimate of the solution vector. On output X contains the final estimate of the solution vector.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM