简体   繁体   中英

python scipy fsolve recursive function

scipy.optimize.fsolve does not appear to work for a function that calls itself. Here is a MWE

from scipy.optimize import fsolve
def f(x):
    if f.n==0:
        return x
    f.n -= 1
    return 1+f(x)
# Consider n=2 i.e. f(x) = 1 + 1 + x = 2 + x
f.n=2
soln = fsolve(f, -1.5) # Expect [-2]
print(soln) # [0.]

Compare

def g(x):
    return 1 + 1 + x
soln = fsolve(g, -1.5)
print(soln) # [-2.]

Is there a workaround for using fsolve with such a function? My use case is that I have a function defined by a recursive formula that would take very long time to type out by hand for large n .

The problem is not that fsolve isn't able to handle recursive functions, but the issue is that your recursive function is polluting the global namespace for recursion. Adding a simple print statement helps make it clearer what is going on.

from scipy.optimize import fsolve
def f(x):
    print(f.n)
    if f.n==0:
        return x
    f.n -= 1
    return 1+f(x)
# Consider n=2 i.e. f(x) = 1 + 1 + x = 2 + x
f.n=2
soln = fsolve(f, -1.5) # Expect [-2]
print(soln) # [0.]

Output:

2
1
0
0
0
0
0
0
[0.]

A solver essentially has to run the function with different inputs and guess the next "best" value to run for iteratively. With a function that relies on global variables, your function "state" itself is unstable and the first time a function is run, the global variables get affected, and your function no longer have the correct global variables to run correctly for the next iteration of the solver.

You need to modify your recursive function and make it self-contained with explicit argument passing.

from scipy.optimize import fsolve
def f(x, state):
    print(state)
    if state==0:
        return x
    state -= 1
    return 1+f(x, state)
# Consider n=2 i.e. f(x) = 1 + 1 + x = 2 + x
state=2
soln = fsolve(lambda x: f(x, state), -1.5) #wrapping the 2 arg recursive function with a lambda to mimic a 1 argument function. You may also use functools.partial for this.
print(soln) 

Output:

2
1
0
2
1
0
2
1
0
2
1
0
2
1
0
2
1
0
[-2.]

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