【问题标题】:Converting a math problem to dynamic programming将数学问题转换为动态规划
【发布时间】:2020-03-28 05:05:57
【问题描述】:

目前,我正在为我和一位同学一起做的一门课程研究一个优化问题。基本上用三个方程来描述。

其中 n 是一个取值在 1 到 1180 之间的索引,Pr 是一个已知向量(意味着该向量的所有值都是已知且恒定的),我们必须找到向量 Ps 导致 Ef[1180] 的最小值。

从逻辑上讲,答案是将 Ps[n] 的所有值设置为无穷大。但是,有一些限制:

此外,EsPs 的值必须始终为 1,000 的倍数以减小状态空间。

以上是我们从作业描述中得出的。但是,我们似乎无法弄清楚如何将其作为动态规划问题来解决。从一组方程到动态规划问题有很多例子。但是,这些示例都有两个或三个输入,并分别使用 2 维或 3 维字典。以方便数据重用。我们基本上有 1180 个输入。创建一个1180维的字典是不可行的

我们尝试为这个问题构建贝尔曼方程,但教授告诉我们这是错误的。然后我们考虑暴力破解状态空间,但这是一项疯狂的工作,因为输入向量 P_s 有 43^1180 种可能的组合。我们的一些同学建议我们查看此维基百科页面上的棋盘示例:

Wikipedia page on dynamic programming

但是,这个例子似乎只遍历了棋盘一次。成本函数的使用总是会为 Ps[n] 选择最高可能的值,以最小化 Ef[n]。但是,要选择这样一个正值,我们必须有 Es[n] > 0,这只会发生在 Ps[i] 的先前元素 for i 取负值。但是成本函数将防止 Ps 具有负值。由于成本函数不允许负值并且 Es[n] >= 0 约束不允许负值,这将导致 Ps 仅包含零,这当然不会导致 Ef[1180] 的最低值。

任何关于如何继续的提示都会很好。我们已经盯着这个问题好几天了,现在我们完全迷失了。

【问题讨论】:

  • 什么是a_m,负数,正数?
  • 好问题,它是肯定的:2.42。
  • 我从朋友那里得到了一些帮助,我正在研究解决方案。当我解决它时,我会发布。但是,如果您有一些提示,请随时发表评论!

标签: algorithm dynamic dynamic-programming


【解决方案1】:

你想最小化 E[1180] 同上最大化 f 定义如下:

f(P) = \sigma_{i=1}^{1180} P_i

在约束下:

forall n <= 1180
  -6.5*10^5 <= \sum_{i=1}^n P_i <= 0

递归公式如下

f(i, sumPs, v) {
  if i == 1180
    return { s: sumPs, solution: v }

  res = { s: -infinity, solution: [] }
  # Pr(i) > Ps(i)
  for psi in -21:min(Pr[i], 21)
    # Es(n-1) = - sumPs
    if psi <= -sumPs
      tmp = f(i+1, sumPs + psi, v+[psi])
      if tmp.s > res.s
        res.s = tmp.s
        res.v = tmp.v
  return res
}
f(0, 0, [])

动态方法类似:

初始化第一层:以sumPs为键、{s:sum, v:facultative}为值的关联数组

我们实际上可以不存储任何值并使用集合(存储总和),但它便于调试目的

初始化

for psi in -21:min(Pr[0], 0)
  layer[psi] = {s: psi, v:[psi]}

要构建层i+1,你只需要层i

for i = 2:1180
  nextLayer = []
  for psi in range(-21, min(Pr[i-1], 21))
    for candidate in layer:
      if psi <= -candidate.s
        maybe = candidate.s + psi
        if !nextLayer[maybe]
          nextLayer[maybe] = {s: maybe, v:v+[psi]}
  layer = nextLayer

注意:我没有处理 1000 因子,但这应该不是问题

const Pr = [-10,2,-2,4,-1]
function f(i, sumPs, v) {
  if (i == 5) {
    return { s: sumPs, v }
  }

  let res = { s: -1e12, v: [] }
  for (let psi = -21; psi<=Math.min(Pr[i], 21); ++psi) {
    if (psi <= -sumPs) {
      let tmp = f(i+1, sumPs + psi, v.concat(psi))
      if (tmp.s > res.s) {
        res.s = tmp.s
        res.v = tmp.v
      }
    }
  }
  return res
}

function dp(n, pr){
  let layer = new Map
  for (let psi = -21; psi <= Math.min(Pr[0], 0); ++psi) {
    layer.set(psi, {s: psi, v:[psi]})
  }
  for (let i = 2; i <= n; ++i) {
    let nextLayer = new Map
    for (let psi = -21; psi <= Math.min(pr[i-1], 21); ++psi) {
      for (let [k, candidate] of layer) {
        if (psi <= -candidate.s) {
          const maybe = candidate.s + psi
          if (!nextLayer.has(maybe)) {
            nextLayer.set(maybe, { s: maybe, v: candidate.v.concat(psi) })
          }
        }
      }
    }
    layer = nextLayer
  }
  return [...layer.entries()].sort((a,b) => b[0] - a[0])[0][1]
}

console.log(f(0,0,[]))
console.log(dp(5,Pr))

【讨论】:

  • 我还没有检查你的解决方案,因为我仍在努力实现我正在尝试的实现,但我已经为你的努力投了赞成票。我稍后会回复你。
  • 只要您有想法,按照自己的方式行事总是更好。如果您曾经在我的“提示”路上退缩,我可能会忽略一些限制,但这不应该改变精神
猜你喜欢
  • 2011-10-17
  • 1970-01-01
  • 2012-04-09
  • 2023-01-31
  • 2011-09-23
  • 2013-08-09
  • 1970-01-01
相关资源
最近更新 更多