【问题标题】:Minimization of f(x,y) where x and y are integersf(x,y) 的最小化,其中 x 和 y 是整数
【发布时间】:2009-07-24 14:36:48
【问题描述】:

我想知道是否有人对最小化函数 f(x,y) 有任何建议,其中 x 和 y 是整数。我研究了很多最小化和优化技术,比如 BFGS 和 GSL 中的其他技术,以及数值食谱中的东西。到目前为止,我已经尝试实施几个不同的方案。第一个通过选择最大下降的方向 f(x+1,y),f(x-1,y),f(x,y+1),f(x,y-1) 来工作,并遵循该方向与线最小化。我也尝试过使用下坡单纯形(Nelder-Mead)方法。这两种方法都离最小值很远。它们似乎都适用于更简单的函数,比如找到抛物面的最小值,但我认为两者,尤其是前者,都是为 x 和 y 是实值(双精度值)的函数而设计的。另一个问题是我需要尽可能少地调用 f(x,y) 。它与外部硬件对话,每次通话需要几秒钟。对此的任何想法将不胜感激。

这是错误函数的示例。抱歉,我之前没有发过这个。这个函数需要几秒钟来评估。此外,我们从设备查询的信息如果低于我们的期望值,则不会添加到错误中,只有当它高于时

double Error(x,y)
{
  SetDeviceParams(x,y);
  double a = QueryParamA();
  double b = QueryParamB();
  double c = QueryParamC();
  double _fReturnable = 0;
  if(a>=A_desired)
  {
    _fReturnable+=(A_desired-a)*(A_desired-a);
  }
  if(b>=B_desired)
  {
    _fReturnable+=(B_desired-b)*(B_desired-b);
  }
  if(c>=C_desired)
  {
    _fReturnable+=(C_desired-c)*(C_desired-c);
  }
  return Math.sqrt(_fReturnable)
}

【问题讨论】:

  • 对您的函数的类和行为的任何想法也将不胜感激。
  • 有趣的问题。有趣的是,当您开始学习分数和实数时,数学首先变得困难,而一旦您删除这些并回到自然数,数学又变得困难了。 =)
  • 你知道 f(x, y) 的方程式吗?
  • 这不是一个真正的编程问题。但它比“为什么我的相机不能在我的笔记本电脑上工作?”更有趣。所以我没说什么!
  • 当然是编程问题。除非您认为算法不是程序。我,我认为任何不是算法的东西都不是编程问题。例如,我如何用语言 Y 做 X——一个语言问题,而不是编程问题。

标签: c# algorithm numerical-analysis minimization


【解决方案1】:

这里有很多很多的解决方案。事实上,有基于该主题的整本书和学科。我现在正在阅读一本优秀的:How to Solve It: Modern Heuristics

没有一种解决方案是正确的 - 根据您对功能的具体了解,不同的解决方案具有不同的优势。甚至已经证明,没有一种启发式算法在所有优化任务中表现最好。

如果你知道你的函数是二次的,你可以使用Newton-Gauss一步找到最小值。遗传算法可以是一个很好的通用工具,或者您可以尝试模拟退火,这不太复杂。

【讨论】:

  • 为什么我的链接坏了?在预览中看起来不像这样。
【解决方案2】:

你看过遗传算法吗?他们非常非常擅长寻找最小值和最大值,同时避免局部最小值/最大值。

【讨论】:

  • 嗯,他们会逐渐变得更好,一次一代!
  • 虽然它们是非线性的 :)
【解决方案3】:

你如何定义 f(x,y) ?最小化是一个难题,具体取决于函数的复杂性。

遗传算法可能是一个很好的候选者。

资源:

Genetic Algorithms in Search, Optimization, and Machine Learning

Implementing a Genetic Algorithms in C#

Simple C# GA

【讨论】:

【解决方案4】:

如果它是一个任意函数,那么就没有很好的方法。

假设我们有一个函数定义为:

f(x, y) = 0 for x==100, y==100
          100 otherwise

任何算法如何实际找到 (100, 100) 作为最小值?它可以是任何可能的值组合。

你对你正在测试的函数了解任何事情吗?

【讨论】:

  • f(x,y) 是一个校准误差函数。我对两个参数感兴趣。两者都受 x 和 y 变化的影响。该函数是相当连续的,但它的导数可能不是,因为只要有一个参数符合规范,我就把它设置为 0
  • @Jon Skeet:这当然是假设函数可以是anything,这确实迫使你尝试(x, y) 的每一种组合。如果你知道函数是伪连续的,事情就会大大简化。
  • @Noldorin:这就是为什么我问 OP 对这个函数了解多少。在我发帖的时候,我给出的功能会满足我们所知道的一切。
  • @Jon Skeet:确实,您发布的函数是一个相当随意的函数示例。但是,该函数不是完全任意的可能性很小(正如我们现在所知,它不可能是一个错误函数),这意味着肯定会有更好的方法。
【解决方案5】:

您通常在数学中寻找的是optimisation technique。一般来说,它们适用于实值函数,但许多可以适用于整数值函数。

特别是,我建议您查看non-linear programminggradient descent。两者似乎都非常适合您的应用程序。

如果您可以提供更多详细信息,我或许可以提出更具体的建议。

【讨论】:

  • 正如我之前所说,它将用于校准程序,因此会有很多设备的误差函数具有相似但不相同的形状。我不知道确切的形状是什么样的,因为我需要获取很多数据。 x 和 y 都在 0 到 65535 之间,收集一条数据需要几秒钟。
  • @Tim:很公平。但是,您能否给我们这个误差函数的形式?如果请求需要几秒钟,我对这里的成功并不十分乐观!
  • 基本上就是这样。如果它有点模棱两可,我很抱歉。双错误(x,y){SetDeviceParams(x,y);双 a = QueryParamA();双 b = QueryParamB();双 c = QueryParamC();双 _fReturnable = 0 if(a>=A_desired) { _fReturnable+=(A_desired-a)*(A_desired-a); } if(b>=B_desired) { _fReturnable+=(B_desired-b)*(B_desired-b); } if(c>=C_desired) { _fReturnable+=(C_desired-c)*(C_desired-c); } 返回 Math.sqrt(_fReturnable) }
  • +1 为避免陷入局部最小值,请尝试从随机起始位置运行梯度下降几次
  • @Gabe:是的,没错。除非您非常清楚最小值的附近位置,否则您需要从一系列起点运行算法。
【解决方案6】:

Jon Skeet 的回答是正确的。你确实需要关于 f 及其导数的信息,即使 f 处处是连续的。

理解您所问问题的困难的最简单方法(仅在整数值处最小化 f)就是考虑一个 f:R->R(f 是实数的实数值函数)的一个变量在单个整数之间进行较大的偏移。您可以轻松地构造这样一个函数,使得实线上的局部最小值与整数处的最小值之间没有相关性,并且与一阶导数没有关系。

对于任意函数,我认为除了蛮力之外别无他法。

【讨论】:

  • 根据我所做的测试,梯度无处不在,所以函数在整数值之间变化不大,但我无法预测它会朝哪个方向变化。蛮力是行不通的,因为获取一条数据需要很长时间
  • 所以你现在是说除了只查看整数值的问题之外你不知道 f 并且你只会对 {(x,y)} 的一个子集进行采样并尝试从有限的子集中得出结论?
  • @pgast 不幸的是,这就是我要说的。我有足够的数据可以很好地猜测起点,但仅此而已。好消息是我不一定关心“最佳”解决方案,只要我得到的解决方案符合规范
  • 如果这是一个依赖生命的应用程序,那么我会开始寻找另一份工作,因为你被要求做的是疏忽第一笔订单。如果不是,那么我可能会通过智能选择子集来强制它。 nsamples,您可以采集的样本数量的限制是多少?我会尝试在 64Kx64 上叠加一个网格,使得网格点的数量为 nsamples,在网格点处采样并选择最小值。
  • 如果你对函数有真正的了解,那么初始网格可能有更少的点,比如 nsamples-m,你和你可以使用最后 m 个采样来暴力破解第一个(nsamples -m) 样本如果我了解您,您正在搜索 (x,y) 参数对以设置设备以减小错误
【解决方案7】:

让我们来看看你的数学问题。这一切都假设我理解 你的问题完全。如果我错了,请随时纠正我。

我们希望最小化以下内容:

\sqrt((a-a_desired)^2 + (b-b_desired)^2 + (c-c_desired)^2)

或其他表示法 ||Pos(x - x_desired)||_2

其中 x = (a,b,c) 和 Pos(y) = max(y, 0) 表示我们想要“积极的部分”(这说明 对于您的 if 语句)。最后,我们希望限制自己 x 为整数值的解。

与上面的海报不同,我认为遗传算法根本不是你想要的。
事实上,我认为解决方案要容易得多(假设我理解你的问题)。

1) 对上述函数运行任何优化例程。这会给你 解 x^* = (a^*, b^*,c^*)。由于此功能正在增加 对于变量,您可以希望的最佳整数解决方案是 (ceil(a^*),ceil(b^*),ceil(c^*)).

现在你说你的函数可能很难评估。存在工具 为此,这不是基于启发式的。以无衍生品的名义进行 优化。人们使用这些工具基于模拟优化目标(我有 甚至听说过一个目标函数是基于作物产量的情况!)

这些方法中的每一种都有不同的属性,但一般来说,它们都试图 不仅要尽量减少目标,还要尽量减少目标函数评估的次数。

【讨论】:

  • +1 用于无导数优化,但数学-y 重述可以使用明确提及“x”是一个函数这一事实,并且可能重命名“x”以便它不会发生冲突使用来自发布源的变量。
  • x 不是函数,只是将变量 a、b、c 集合到一个向量中。
  • Tim 不想最小化Err_A(x) = ||Pos(x - A)||₂,而是Err_A(Dev(u)),其中Dev(u):Z² -> R³。如果溶液。在x 中,它不需要是整数。此外,ceil·x' 可能不是有效的解决方案。在x 中,因为可能没有u' 这样ceil·x'=Dev(u')。对于Dev 到一些Dev'(u):R² -> R³ 的扩展,我可以想象(露台、网格),solns。在u 中将是整数值。如果奇异的Dev'(u) 的最小值为u'∉Z²,则{ceil, floor}² · u' 的元素可能不是解决方案。
  • 有趣...我需要再考虑一下,但显然我在他的函数 def 中理解了一些东西。尽管如此,我认为还有其他我知道的非启发式解决方案在工业中用于此类问题......一个例子是 MADS。
  • Dev 代表设备。这是他的 Error(x,y) 函数的前 4 行。
【解决方案8】:

抱歉,之前的格式太差了。这是一个错误函数的例子

double Error(x,y)
{
SetDeviceParams(x,y);
double a = QueryParamA();
double b = QueryParamB();
double c = QueryParamC();
double _fReturnable = 0;
if(a>=A_desired)
{
  _fReturnable+=(A_desired-a)*(A_desired-a);
}
if(b>=B_desired)
{
 _fReturnable+=(B_desired-b)*(B_desired-b);
}
if(c>=C_desired)
{
  _fReturnable+=(C_desired-c)*(C_desired-c);
}
return Math.sqrt(_fReturnable)
}

【讨论】:

  • 啊,好吧,我已经为你做了。格式最终有所不同,因为我愚蠢地从显示的文本而不是编辑文本中复制。
猜你喜欢
  • 1970-01-01
  • 2013-04-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-27
相关资源
最近更新 更多