【问题标题】:Algorithm for shortening a series of actions?缩短一系列动作的算法?
【发布时间】:2008-11-25 13:43:57
【问题描述】:

自从我在学校上算法课已经有一段时间了,如果我的术语不准确,请原谅我。

我有一系列动作,在运行时会产生一些所需的状态(它基本上是一组重现错误的步骤,但就这个问题而言,这并不重要)。

我的目标是找到仍能产生所需状态的最短步骤系列。任何给定的步骤都可能是不必要的,因此我正在尝试尽可能有效地删除这些步骤。

我想保留步骤的顺序(这样我可以删除步骤,但不能重新排列它们)。

我采取的幼稚方法是采取整个系列并尝试删除每个操作。如果我成功地删除了一个动作(不改变最终状态),我会从系列的开头重新开始。在最坏的情况下,这应该是 O(n^2)。

我开始尝试提高效率的方法,但我很确定这是一个已解决的问题。不幸的是,我不确定谷歌到底是什么——这个系列并不是真正的“路径”,所以我不能使用路径缩短算法。任何帮助——即使只是给我一些搜索条件——都会有所帮助。

更新:有几个人指出,即使是我的幼稚算法也找不到最短的解决方案。这是一个很好的观点,所以让我稍微修改一下我的问题:关于同一问题的近似算法的任何想法?我宁愿有一个快速接近最短解决方案的简短解决方案,也不愿花很长时间来保证绝对最短的系列。谢谢!

【问题讨论】:

  • 我所描述的分治法应该可以作为具有许多不相关步骤的大 n 的近似值,就像我在扩展答案中指出的那样。
  • 我不明白你为什么说调试无关紧要:如果是,那么 Delta Debugging 将帮助您自动最小化一组导致源代码更改的输入 OR 的失败正如 Hasturkun 所指出的,隔离错误等。请澄清。

标签: algorithm


【解决方案1】:

您幼稚的 n^2 方法并不完全正确;在最坏的情况下,您可能必须查看所有子集(实际上,更准确的说法是这个问题可能是 NP 难的,这并不意味着“可能必须查看所有子集”,但无论如何.. .)

例如,假设您当前正在运行步骤 12345,并且您开始尝试单独删除每个步骤。然后你可能会发现你不能去掉 1,你可以去掉 2(所以你去掉它),然后你看 1345,发现它们每个都是必不可少的——一个都不能去掉。但实际上,如果你保留 2,那么“125”就足够了。

如果产生给定结果的集合族不是单调的(即,如果它不具有如果某组动作有效,那么任何超集都有效的属性),那么您可以证明不存在无需查看所有子集即可找到最短序列的方法。

【讨论】:

  • 非常好。好的,关于同一问题的近似算法有什么想法吗?我不一定需要最短的系列:在我的应用程序中快速找到一个非常短的系列比慢慢地找到绝对最短的系列要好。谢谢!
【解决方案2】:

如果您对每个动作的效果完全不做任何假设,并且想要找到最小的子集,那么您将需要尝试所有可能的动作子集以找到最短的序列。

所述的二分搜索方法仅在单个步骤导致您想要的状态时就足够了。

对于更一般的状态,即使一次删除一个操作也不一定会给您最短序列。如果您考虑一些病态的例子,即动作可能一起不会导致问题,但会单独触发您想要的状态,就会出现这种情况。

您的问题似乎可以简化为更一般的搜索问题,并且您可以创建的假设越多,您的搜索空间就会变得越小。

【讨论】:

  • 不,您没有阅读我的回答。这是二分搜索启发;它确实 not 每次都丢弃一半的搜索空间,正如我明确说的那样,您的递归 both 一半。
  • 我的道歉,无意冒犯,我是从这样的角度说的,通过保持两半你失去了相对于扫描方法的优势。
【解决方案3】:

Delta Debugging,一种最小化一组故障诱导输入的方法,可能是一个不错的选择。
我之前使用过Delta(最小化“有趣”文件,基于对趣味性的测试)将大约 1000 行的文件减少到大约 10 行,以获取错误报告。

【讨论】:

    【解决方案4】:

    想到的最明显的事情是二分搜索启发的递归分割成两半,你交替地省略每一半。如果在递归的任何阶段遗漏一半仍然重现结束状态,则将其遗漏;否则,将其放回并在该一半的两半上递归,等等。

    在两半上递归意味着它会在放弃并尝试这些块中的较小块之前尝试消除大块。在最坏的情况下,运行时间将是 O(n log(n)),但如果你有一个很大的 n 并且很可能有许多不相关的步骤,它应该在 O(n) 尝试省略的方法之前获胜每次一个步骤(但不重新开始)。

    该算法只会找到一些最小路径,但是,它无法找到由于组合步间效应而可能存在的较小路径(如果这些步骤确实具有这种性质)。但是,找到所有这些将导致组合爆炸,除非您有更多关于推理步骤的信息(例如依赖关系)。

    【讨论】:

      【解决方案5】:

      您的问题域可以映射到有向图,其中状态为节点,步骤为链接,您想在图中找到最短路径,为此存在许多众所周知的算法,例如 Dijkstra'sA*

      更新:

      让我们考虑一个简单的情况,您有一个步骤从状态 A 到状态 B,这可以绘制为通过链接连接的 2 个节点。现在你有另一个步骤从 A 到 C 和从 C 你有一步到 B A-B)。 因此,您可以看到成本函数实际上非常简单,您为达到目标所采取的每一步都加 1。

      【讨论】:

      • 恐怕我不知道这样的映射是如何工作的——每一步都没有图表中的成本。必要与否,是否必要可能取决于其他步骤。
      猜你喜欢
      • 2011-06-02
      • 1970-01-01
      • 1970-01-01
      • 2011-09-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-30
      相关资源
      最近更新 更多