26

の (簡単な) ドキュメントにscipy.integrate.odeは、2 つのメソッド (dopri5およびdop853) にはステップサイズ制御と高密度出力があると記載されています。例とコード自体を見ると、インテグレーターから出力を取得するための非常に単純な方法しかわかりません。つまり、固定された dt だけ積分器を進め、その時点で関数値を取得し、繰り返すように見えます。

私の問題はかなり可変的なタイムスケールを持っているので、必要な許容範囲を達成するために評価する必要がある時間ステップで値を取得したいと思います。つまり、早い段階で物事がゆっくりと変化しているため、出力の時間ステップが大きくなる可能性があります。しかし、物事が面白くなるにつれて、出力のタイム ステップを小さくする必要があります。実際には、等間隔で高密度の出力は必要ありません。適応関数が使用する時間ステップが必要なだけです。

編集:密な出力

関連する概念 (ほぼ反対) は「高密度出力」です。これにより、実行されるステップは、ステッパーが実行するのと同じくらい大きくなりますが、関数の値は (通常、ステッパーの精度に匹敵する精度で) 補間されます。あなたがしたい。基礎となる fortranscipy.integrate.odeは明らかにこれが可能ですodeが、インターフェースがありません。 odeint一方、は別のコードに基づいており、明らかに高密度の出力を行います。(右側が呼び出されるたびに出力して、それがいつ発生するかを確認し、出力時間とは関係がないことを確認できます。)

したがって、事前に必要な出力時間ステップを決定できる限り、適応性を利用することができます。残念ながら、私のお気に入りのシステムでは、統合を実行するまで、時間の関数としてのおおよそのタイムスケールが何であるかさえわかりません。したがって、積分器を 1 ステップ実行するというアイデアと、この高密度出力の概念を組み合わせる必要があります。

EDIT 2:再び密な出力

どうやら、scipy 1.0.0 では、新しいインターフェイスを介した高密度出力のサポートが導入されました。特に、キーワードとしてのから離れscipy.integrate.odeintたり近づいたりすることを推奨しています。に設定すると、返されるオブジェクトには、時間の配列で呼び出すことができる属性が含まれます。この属性は、それらの時間に統合された関数の値を返します。それでもこの質問の問題は解決しませんが、多くの場合に役立ちます。scipy.integrate.solve_ivpdense_outputTruesol

4

5 に答える 5

14

私はこれを見て、同じ結果を得ようとしました。ode のインスタンス化で nsteps=1 を設定することにより、ハックを使用して段階的な結果を取得できることがわかりました。すべてのステップで UserWarning が生成されます (これはキャッチして抑制することができます)。

import numpy as np
from scipy.integrate import ode
import matplotlib.pyplot as plt
import warnings


def logistic(t, y, r):
    return r * y * (1.0 - y)

r = .01
t0 = 0
y0 = 1e-5
t1 = 5000.0

#backend = 'vode'
backend = 'dopri5'
#backend = 'dop853'

solver = ode(logistic).set_integrator(backend, nsteps=1)
solver.set_initial_value(y0, t0).set_f_params(r)
# suppress Fortran-printed warning
solver._integrator.iwork[2] = -1

sol = []
warnings.filterwarnings("ignore", category=UserWarning)
while solver.t < t1:
    solver.integrate(t1, step=True)
    sol.append([solver.t, solver.y])
warnings.resetwarnings()
sol = np.array(sol)

plt.plot(sol[:,0], sol[:,1], 'b.-')
plt.show()

結果:

于 2013-01-22T22:01:50.330 に答える
8

このメソッドは、単一の内部ステップを返すようにメソッドに指示integrateするブール引数を受け入れます。stepただし、「dopri5」および「dop853」ソルバーはこれをサポートしていないようです。

次のコードは、「vode」ソルバーが使用されている場合にソルバーが実行する内部ステップを取得する方法を示しています。

import numpy as np
from scipy.integrate import ode
import matplotlib.pyplot as plt


def logistic(t, y, r):
    return r * y * (1.0 - y)

r = .01

t0 = 0
y0 = 1e-5
t1 = 5000.0

backend = 'vode'
#backend = 'dopri5'
#backend = 'dop853'
solver = ode(logistic).set_integrator(backend)
solver.set_initial_value(y0, t0).set_f_params(r)

sol = []
while solver.successful() and solver.t < t1:
    solver.integrate(t1, step=True)
    sol.append([solver.t, solver.y])

sol = np.array(sol)

plt.plot(sol[:,0], sol[:,1], 'b.-')
plt.show()

結果: ソリューションのプロット

于 2012-10-17T13:36:31.257 に答える
2

参考までに、回答は既に受け入れられていますが、過去の記録として、計算された軌跡に沿ったどこからでも高密度の出力と任意のサンプリングがPyDSToolでネイティブにサポートされていることを指摘しておく必要があります。これには、ソルバーによって内部的に使用されるすべての適応的に決定された時間ステップの記録も含まれます。これはdopri853 と radau5の両方と連携し、右側の定義の (はるかに遅い) python 関数コールバックに依存するのではなく、それらとの連携に必要な C コードを自動生成します。私の知る限り、これらの機能はいずれも、他の Python に焦点を当てたソルバーではネイティブまたは効率的に提供されていません。

于 2015-11-04T01:54:21.800 に答える