最近、GSL を使用して非常に奇妙な問題に遭遇しました。GSLに関数の負のイメージの最小値を見つけるように依頼することにより、醜い関数の最大値を見つけようとしています。これは、これまで使用してきたほとんどの機能で正常に機能していますが、特定の機能でエラーが発生します。
具体的には、Ruby GSL gem は、関数を minimum-finder にフィードすると、指定されたエンドポイントが最小値を囲んでいないことを示す例外をスローします。ただし、指定されたエンドポイントは最小値を囲みます。さらに、結果は与えられた最初の見積もりに依存するようです。
GSL に 0.0 の推測から始まる最小値を見つけるように依頼すると、エラーが発生します。推測値 2.0 から始めて最小値を見つけるように依頼すると、最小値が見つかります。GSL が、最初の推測に基づいて、与えられた間隔に最小値がないと文句を言うのは奇妙に思えます。
以下は、このエラーを再現するために作成したスクリプトです。私は GSL バージョン 1.15 と Ruby バージョン 1.9.3p392 の最新バージョンの Ruby/GSL gem ラッパーを使用しています。
誰かがこのスクリプトを試して、これらの結果を再現できるかどうかを確認してください。これをバグとして GSL メンテナに報告したいのですが、他の人のコンピュータでもエラーが発生するようにできれば、報告したほうがよいでしょう。
スクリプトで提供される初期最小推定値には 3 つの値があります。0.0 で始まると、GSL は前述のエラーをスローします。1.0 から開始すると、GSL は最小値を報告しますが、これはたまたま局所的な最小値にすぎません。2.0 から始めると、GSL が別の最小値を報告するようになります。これは、私が探している全体的な最小値のようです。
ここに私のテストスクリプトがあります:
require("gsl")
include GSL::Min
function = Function.alloc { |beta| -(((6160558822864*(Math.exp(4*beta))+523830424923*(Math.exp(3*beta))+1415357447750*(Math.exp(5*beta))+7106224104*(Math.exp(6*beta)))/(385034926429*(Math.exp(4*beta))+58203380547*(Math.exp(3*beta))+56614297910*(Math.exp(5*beta))+197395114*(Math.exp(6*beta))))-((1540139705716*(Math.exp(4*beta))+174610141641*(Math.exp(3*beta))+283071489550*(Math.exp(5*beta))+1184370684*(Math.exp(6*beta)))*(1540139705716*(Math.exp(4*beta))+174610141641*(Math.exp(3*beta))+283071489550*(Math.exp(5*beta))+1184370684*(Math.exp(6*beta)))/(385034926429*(Math.exp(4*beta))+58203380547*(Math.exp(3*beta))+56614297910*(Math.exp(5*beta))+197395114*(Math.exp(6*beta)))**2)) }
def find_maximum(fn1)
iter = 0; max_iter = 500
minimum = 0.0 # reasonable initial guess; causes GSL to crash!
#minimum = 1.0 # another initial guess, gets a local min
#minimum = 2.0 # this guess gets what appears to be the global min
a = -6.0
b = 6.0
#pretty wide interval
gmf = FMinimizer.alloc(FMinimizer::BRENT)
gmf.set(fn1, minimum, a, b)
#THIS line is failing (sometimes), complaining that the interval given doesn't contain a minimum. Which it DOES.
begin
iter += 1
status = gmf.iterate
status = gmf.test_interval(0.001, 0.0)
# puts("Converged:") if status == GSL::SUCCESS
a = gmf.x_lower
b = gmf.x_upper
minimum = gmf.x_minimum
# printf("%5d [%.7f, %.7f] %.7f %.7f\n",
# iter, a, b, minimum, b - a);
end while status == GSL::CONTINUE and iter < max_iter
minimum
end
puts find_maximum(function)
このコードを試してみるとどうなるか教えてください。最小値のさまざまな初期値をコメントアウトしてください。これが実際に GSL の意図した動作である理由がわかれば、それも感謝します。
ご協力ありがとうございました!