HOWTO · Python
Python で Fsolve を使用する
この記事では、Python で fsolve を使用する方法を示します。
このページの内容
scipy.optimize.fsolve は、非線形関数がゼロになる値を数値的に探索します。このガイドでは、SciPy のインストール方法、スカラー方程式または連立方程式の解き方、初期値の選び方、ソルバーの結果の確認方法を説明します。
fsolve が解く問題
fsolve は、SciPy の scipy.optimize モジュールに含まれる関数です。局所的な数値計算法を使い、func(x) = 0 の根を求めます。x には1つ以上の未知数を含められます。連立方程式の場合、func は未知数ごとに1つの残差を返し、根ではすべての残差がゼロに近くなります。
数値ソルバーを使っても、根の存在や一意性、ほかに根がないことは証明できません。ソルバーは指定された初期値から探索するため、初期値によって異なる根に収束することがあります。返された値を利用する前に、ソルバーの収束情報と、対象の問題における残差の両方を確認してください。
SciPy をインストールして fsolve をインポートする
スクリプトを実行する Python 環境に SciPy をインストールするには、python -m pip install scipy を実行します。スクリプトでは、from scipy.optimize import fsolve のように関数をインポートします。その環境に SciPy がすでにインストールされていれば、インストール作業は不要です。
スカラー非線形方程式を解く
未知数が1つの場合は、入力配列を受け取り、残差を返す関数を定義します。この例では、正の根に近い値を初期値として x² - 2 = 0 を解きます。
次の例を実行します。
このセクションのコードと表示されるラベルや出力は英語のままです。
from scipy.optimize import fsolve
def residual(x):
return x[0] ** 2 - 2
root, info, ier, message = fsolve(residual, [1.0], full_output=True)
print("root:", root[0])
print("residual:", residual(root))
print("converged:", ier == 1)
root: 1.4142135623730947
residual: -8.881784197001252e-16
converged: True
fsolve は x を配列として渡すため、関数はその唯一の要素を x[0] で読み取ります。返される root も配列形式です。full_output=True を指定すると、呼び出しは解、情報辞書、整数のステータス、メッセージを返します。ステータス値 1 は、ソルバーが収束したと報告していることを示します。それでも、用途に必要な精度が得られているか、残差を確認してください。
非線形方程式の連立系を解く
連立系では、未知数ベクトルと同じ長さの残差列を返します。この例では、未知数が2つ、方程式が2つです。方程式は x² + y² - 5 = 0 と x - y - 1 = 0 で、初期ベクトルは解 (2, 1) に近い値です。
このセクションのコードと表示されるラベルや出力は英語のままです。
from scipy.optimize import fsolve
def equations(values):
x, y = values
return [x**2 + y**2 - 5, x - y - 1]
initial_guess = [1.8, 0.8]
solution, info, ier, message = fsolve(
equations, initial_guess, full_output=True
)
print("solution:", solution)
print("residuals:", equations(solution))
print("converged:", ier == 1)
solution: [2. 1.]
residuals: [np.float64(-2.3092638912203256e-14), np.float64(0.0)]
converged: True
initial_guess の2つの要素は、それぞれ x と y に対応します。関数は方程式と同じ順序で2つの残差を返します。残差の数と未知数の数を一致させてください。複数の根を持つ連立系では、初期ベクトルによって局所反復がどの根に近づくかが変わることがあります。
初期値を選び、結果を確認する
可能であれば、x0 には根として妥当そうな値の近くを選びます。ソルバーはその初期値から局所的に探索するため、根から遠い値やスケールの合わない値を指定すると、収束しなかったり、別の根に収束したり、用途に適さない点に到達したりすることがあります。複数の根が考えられる場合は、モデルに基づいた複数の初期値を試し、返された解を比較してください。
診断情報が必要な場合は、full_output=True を設定し、ier と mesg(例では message という名前)を確認します。ステータス 1 はソルバーの停止条件に従って収束したことを示しますが、モデルが正しいことや、残差が用途に十分小さいことを示すものではありません。func(solution) を直接評価し、各残差を問題の単位やスケールに合った許容誤差と照らし合わせてください。結果が適切でない場合は、返された数値を根の証明とみなさず、初期値、スケーリング、モデル、またはソルバーの選択を見直してください。
fsolve の主なパラメーターと制限を理解する
呼び出しの形式は次のとおりです。fsolve(func, x0, args=(), fprime=None, full_output=False, col_deriv=False, xtol=1.49012e-8, maxfev=0, band=None, epsfcn=None, factor=100, diag=None)。完全なシグネチャと戻り値については、SciPy の公式 fsolve リファレンスを参照してください。
funcは残差をゼロに近づける関数です。現在の推定値と、argsから渡された追加の値を受け取ります。x0は初期推定値です。未知数が1つならスカラー相当の値、連立系ならベクトルを指定できます。例では、関数が一貫した形式で入力を扱えるよう配列を使っています。argsは、推定値の後にfuncへ渡す追加引数のタプルです。fprimeは、導関数のヤコビ行列を任意で指定します。既定では、行が残差関数、列が変数に対応します。full_outputを指定すると、解に加えて診断情報、ステータス、メッセージが返されます。col_derivは、指定したヤコビ行列が導関数を列方向に計算することを示します。転置を避けられるため、fprimeを指定した場合に関係します。xtolは、連続する反復間の相対誤差許容値を設定します。この停止条件を満たしても、残差が小さいとは限りません。maxfevは関数の評価回数を制限します。値がゼロの場合、変数の数に基づく SciPy の既定上限が使われます。bandは、SciPy が導関数を推定し、fprimeを指定していない場合に、帯行列ヤコビ行列の下側と上側の帯幅を表します。epsfcnは、fprimeを指定せずに導関数を推定する場合、有限差分の刻み幅の設定に使われます。factorは初期ステップ幅の上限を設定します。指定できる範囲は 0.1 から 100 です。diagは変数のスケール係数として、正の値を任意で指定します。変数の大きさが大きく異なる場合に役立ちます。
fsolve は局所的な根探索関数であり、解が得られることを一般に保証するものではありません。数値的な挙動は、関数、初期推定値、スケーリング、停止条件の設定によって変わります。