简体   繁体   中英

Pass list of values to SciPy fsolve argument

I have the following function:

def equation1(xy, d=7.62, G=8.2728, rhop=7.51, ut=399):
    ep, uc = xy     # define variables
    g = 981         # acceleration due to gravity, cm/s^2

    f1 = 2*g*d*((ep**-4.7) - 1) - 0.01*(uc/ep - ut)**2
    f2 = G - (uc/ep - ut)*rhop*(1 - ep)
    return f1, f2

where I solve for ep and uc by using fsolve in SciPy:

ep1, uc1 = fsolve(equation1, [1, 500])

Instead of defining a single value for G , I would to like solve for ep and uc for a range G values such as G = [8, 10, 12] . When I pass a list of values for G, I get an error about setting an array element with a sequence.

Is it possible to use fsolve where one of the arguments is a list or array of values?

you can keep G as a parameter to equation1 and pass it via fsolve (using its args parameter) as:

from scipy.optimize import fsolve

def equation1(xy, G, d=7.62, rhop=7.51, ut=399):
    ep, uc = xy     # define variables
    g = 981         # acceleration due to gravity, cm/s^2

    f1 = 2*g*d*((ep**-4.7) - 1) - 0.01*(uc/ep - ut)**2
    f2 = G - (uc/ep - ut)*rhop*(1 - ep)
    return f1, f2


for G in [8, 10, 12]:
    ep1, uc1 = fsolve(equation1, [1, 500], (G, ))
    print(G, ep1, uc1)

this gives on my machine:

8 0.994582431487 592.401268397
10 0.993718674117 607.148953105
12 0.992912345764 620.018209488

If I run your function with:

In [83]: ep1, uc1 = fsolve(equation1, [1, 500],args=(7.62, [8,10,12]))
...
ValueError: setting an array element with a sequence.

But look at the call stack. It's long, but this line stands out

res = atleast_1d(thefunc(*((x0[:numinputs],) + args)))

It's making a test call to your function.

So for example:

In [121]: x0=np.array([1,500])
In [122]: numinputs=2
In [123]: args = (1,8)     # scalar G
In [124]: np.atleast_1d(equation1(*((x0[:numinputs],) + args)))
Out[124]: array([-102.01,    8.  ])

In [125]: args = (1,[8,10])    # list G
In [126]: np.atleast_1d(equation1(*((x0[:numinputs],) + args)))
....
ValueError: setting an array element with a sequence.

Looking specifically at what your function produces:

In [127]: equation1(*((x0[:numinputs],) + args))
Out[127]: (-102.01000000000001, array([  8.,  10.]))

It can't turn this tuple into a valid 1d array, hence the error message.

Note that the arguments to your function are:

In [128]: ((x0[:numinputs],) + args)
Out[128]: (array([  1, 500]), 1, [8, 10])

fsolve passes the whole args tuple to your function. It does not iterate through arrays or lists.

So you want fsolve for various G values, you have to do the iteration yourself. fsolve (and most of the other scipy functions) won't do it for you.

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