2017-01-21 30 views
6

次の考えを考えてみましょう:k = 1,...,50の関数のシーケンスf_kと を生成し、Python辞書に格納したいと考えています。具体的な例を与えることを 、これは一例でPythonでの反復関数の生成

f_k(x) = f_{k-1}(x) * sqrt(x) 

を言うことができます、私が持っている問題はより複雑であるが、これは私の質問のために重要ではありません。私の本当の問題にf_{k-1}は非常にノイズが多いと丸め誤差が含まれているため は、私がf_{k-1}から直接f_kを構築したいのですが、スプライン近似によるI最初の近似f_{k-1}代わり し、そのスプライン近似からf_kを決定するものではありません。不思議なことに、この結果、最大再帰深度が超過したというエラーメッセージが表示されます。ここでは、コードの例です:

import numpy as np 
from scipy.interpolate import interp1d 
n = 50 # number of functions I want to create 
args = np.linspace(1,4,20) # where to evaluate for spline approximation 
fdict = dict() # dictionary that stores all the functions 
fdict[0] = lambda x: x**2 # the first function 

# generate function f_k as follows: First, take function f_{k-1} and 
# approximate it through a spline. Multiply that spline approximation 
# by sqrt(x) and store this as function f_k. 
for k in range(1,n+1): 

    spline_approx = lambda x: interp1d(args,fdict[k-1](args))(x) 
    fdict[k] = lambda x: spline_approx(x) * np.sqrt(x) 

print('test evalutation: ', fdict[n](3)) 

これは私の問題は非常にPythonの具体的でなければならない

RecursionError: maximum recursion depth exceeded 

エラーが発生します。 interp1dによる補間とは何か関係があります。例えば、 。私は関数polyfit

coefs = np.polyfit(args,fdict[k-1](args),10) # polyfit coefficients 
spline_approx = lambda x: np.polyval(coefs,x) # approximation of f_{k-1} 

によってライン

spline_approx = lambda x: interp1d(args,fdict[k-1](args))(x) 

を交換した場合、コードは正常に動作します。 fdict[k-1]は直接評価されておらず、参照として渡されるだけなので、問題が発生していると思われます。しかし、どうすればこの問題を解決できますか?

答えて

4

RecursionErrorを上げるラインは確かである:

spline_approx = lambda x: interp1d(args,fdict[k-1](args))(x) 

この行はspline_approxxで評価interp1d(args, fdict[k-1](args)を返しx与えられ、関数であることを意味します。

interp1dはあなたがspline_approxに入れたい機能を返すので、この行はに単純化することができます。RecursionErrorを投げて停止する

spline_approx = interp1d(args,fdict[k-1](args)) 


なぜ、あなたの元のコードはRecursionErrorを投げていますか?

interp1d(args, fdict[k-1](args))は、lambdaの式の中にあるので、と評価されていません。です。この評価は、そのlambda式の呼び出しに延期されます。

つまり、fdictから関数を呼び出すたびに、以前の関数はすべてinterp1d(args, fdict[k-1](args))と評価されなければなりません。問題はargsがシーケンスなので、fdict[k-1]が要素数を持つargsと何度も呼ばれます。

すべての関数が先行関数len(args)回を評価しなければならないので、呼び出し回数はもちろん指数関数です。その結果、RecursionErrorになります。

一方、新しい式ではinterp1d(args, fdict[k-1](args))と評価されます。この評価の後、fdict[k]への呼び出しは、fdict[k-1]への呼び出しをもう一度トリガーしません。

+1

[字句解析](https://stackoverflow.com/questions/233673/lexical-closures-in-python)に言及する価値があります。 – shx2