0

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

具体来说,当我将函数提供给最小值查找器时,ruby GSL gem 会引发异常,指出给定的端点没有包含最小值。但是,给定的端点确实包含最小值;此外,结果似乎取决于给出的初步估计。

当我要求 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 的预期行为的原因,我也将不胜感激。

感谢您的帮助!

4

2 回答 2

0

我认为这个 Mathematica 笔记本完美地总结了我的答案在此处输入图像描述

每当您需要在数值上最小化特定函数时,您必须定性地理解它(制作绘图)以避免由于数值错误而导致失败。该图显示了一个非常重要的事实:您的函数似乎需要在 beta ~ 6 的非常大的数字之间进行数字困难的取消。在 beta ~ -6 时也会出现数字问题。

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

结论:如果最小值在零附近(始终绘制要最小化的函数图!),那么当您的函数依赖于指数之间的精确抵消时,您必须在零附近设置一个小的间隔以避免数值问题。

编辑:在评论中,您要求我不要考虑 Abs[beta] 因素。在这种情况下,GSL 会找到多个局部最小值(=> 你必须减小区间) 在此处输入图像描述。我也无法理解您如何获得 1.93 左右的最小值

于 2013-09-15T01:02:24.377 回答
0

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

于 2021-03-11T17:35:22.767 回答