这是GSL最小发现程序中的错误吗?

时间:2013-09-14 23:49:28

标签: ruby numerical-methods gsl

我最近使用GSL遇到了一个非常奇怪的问题。我试图通过要求GSL找到函数的负图像的最小值来找到最大的丑陋函数。到目前为止,我一直在使用它的大多数功能都可以正常工作,但是对于某些功能,我收到错误。

具体来说,当我将函数提供给最小查找器时,ruby GSL gem抛出一个异常,说明给定的端点没有包含最小值。但是,给定的端点DO包含最小值;此外,结果似乎取决于给出的初始估计。

当我要求GSL找到最小值为0.0的起点时,我得到错误。当我要求它找到2.0的最小起点时,它会找到最小值。奇怪的是,GSL会抱怨在给定的时间间隔内根据初始猜测没有最小值。

下面是我为重现此错误而编写的脚本。我正在使用GSL版本1.15和最新版本的Ruby / GSL gem包装器,Ruby版本1.9.3p392。

有人请尝试这个脚本,看看他们是否可以重现这些结果?我想将此报告为GSL维护者的错误,但如果我能在其他人的计算机上发生错误,我会感觉更好。

脚本中提供的初始最小猜测有三个值;从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的预期行为,我也会很感激。

感谢您的帮助!

2 个答案:

答案 0 :(得分:0)

我认为这个Mathematica笔记本完美地总结了我的答案enter image description here

每当您需要在数字上最小化特定功能时,您必须定性地理解它(制作图表)以避免由于数字错误而导致的故障。这个图显示了一个非常重要的事实:你的函数似乎需要在β~6之间的非常大的数字之间的数字上很难取消。数字问题也可能出现在beta~-6。

然后,当您将间隔设置为[-6,6]时,您的数字错误可能会阻止GSL找到最小值。对潜在危险术语的简单绘图和少量评估可以更好地理解您必须在GSL例程中设置的适当限制。

结论:如果最小值大约为零(总是绘制你想要最小化的函数的图形!),那么你必须设置一个小的零间隔,以避免数字问题,当你的函数取决于指数之间的精确取消。

编辑:在评论中,您要求我不要考虑因素Abs [beta]。在这种情况下,GSL会找到多个局部最小值(=>你必须缩小间隔) enter image description here。我也无法理解你如何得到最低1.93

答案 1 :(得分:0)

只要您的初始猜测的函数值大于或等于区间任一极值处的函数值,GSL 一维最小化例程就会报告此错误。因此,实际上,这取决于您找到一个或另一个局部最小值或根本没有找到的初始猜测。错误信息肯定具有误导性。

相关问题