【问题标题】:Manhattan distance in A*曼哈顿距离 A*
【发布时间】:2012-09-21 08:23:45
【问题描述】:

我正在使用 A* 搜索算法并使用曼哈顿距离作为启发式方法来实现 NxN 谜题求解器,但我遇到了一个奇怪的 错误 (?),我无法理解.

考虑这些谜题(0 元素为空格):
(初始)

1 0 2
7 5 4
8 6 3

(目标)

1 2 3
4 5 6
7 8 0

从初始状态达到解决方案的最少移动次数是 11。但是,我的求解器需要 17 次移动才能达到目标。

这就是问题所在 - 我的解谜器主要以正确(最少)的移动数来解决可解的谜题,但对于这个特定的谜题,我的解谜器超出了最小移动数,我认为我已经解决了问题在这种特殊情况下误算了曼哈顿距离。

在这个link,您可以看到我的求解器在做什么(在右侧)以及一个久经考验的求解器在做什么(Brian Borowski 的优秀求解器,here 可用)。

在第一步中,Brian 的求解器立即选择将元素 5 向上推的解决方案,但我的求解器有其他想法,并且在堆栈跟踪(在 link 上给出)上,我的求解器选择将 2 推到左侧的解决方案(由于该板的曼哈顿距离较低,因此该板位于优先队列的前面)。 我看不出问题出在哪里,也不能怪我的曼哈顿距离计算,因为它正确地解决了许多其他 3x3 难题。

这是我计算给定棋盘的曼哈顿距离的方法:

/**
 * Calculates sum of Manhattan distances for this board and stores it in private field to promote immutability.
 */
private void calculateManhattanDistance() {
    int manhattanDistanceSum = 0;
    for (int x = 0; x < N; x++) // x-dimension, traversing rows (i)
        for (int y = 0; y < N; y++) { // y-dimension, traversing cols (j)
            int value = tiles[x][y]; // tiles array contains board elements
            if (value != 0) { // we don't compute MD for element 0
                int targetX = (value - 1) / N; // expected x-coordinate (row)
                int targetY = (value - 1) % N; // expected y-coordinate (col)
                int dx = x - targetX; // x-distance to expected coordinate
                int dy = y - targetY; // y-distance to expected coordinate
                manhattanDistanceSum += Math.abs(dx) + Math.abs(dy); 
            } 
        }
    manhattanDistance = manhattanDistanceSum;
}

如果您有任何见解或想法,我将不胜感激。

如果需要任何额外的代码,我会立即发布。

【问题讨论】:

  • 你确定这不是你的 A* 实现中的错误,而不是距离启发式?
  • 好吧,我已经想到了,但是如果您检查堆栈跟踪,我实际上认为一切都按预期工作。选择的解决方案是成本最低的解决方案,这就是我们想要的。问题是我将次优移动计算为最佳并选择它作为路径。这就是让我怀疑距离计算的原因,但我看不到错误。
  • 您是否将您的运行与使用 only 曼哈顿距离作为启发式运行的 Brian 求解器进行比较?或者是布赖恩也使用线性冲突(见第二个参考)。让我感到震惊的是,将 MD-wise 移动 2 作为第一步可能确实有意义,但这种“贪婪”的方法通常不是最理想的。 A* 仅与您使用的启发式方法一样好
  • 没错——我只使用 MD 作为启发式。我已经完全设置了应用程序参数以匹配我的求解器。你能在给定的 MD 计算中看到任何错误吗?您对如何避免这种 A*“贪婪”有什么建议吗?
  • 要测试您的 A*,您可以将启发式设置为 0,它将像 Dijkstra 算法一样运行。除非有负权重,否则 Dijkstra 保证返回最优解。

标签: java artificial-intelligence a-star sliding-tile-puzzle


【解决方案1】:

我被困在同一个地方,我用 17 步来解决这个问题。问题是我只对 A* 算法使用启发式 h(n),而在选择下一个节点时,A* 使用 manhattan距离(启发式)+ 路径成本(从根到达节点的成本称为 g(n))来做出选择。 一旦你把它插入到算法中,它就像一个魅力。

希望这可以帮助被困在同一个地方的人。

【讨论】:

  • 对此我感激不尽!我已经被困了一天多,即将放弃
【解决方案2】:

如果您的启发式方法是可接受的(确实如此,请检查this),而不是 A* 总是返回最佳解决方案。可以更慢或更快(扩展更多或更少的节点),但它会返回最佳解决方案。

因此,由于您的启发式是可以接受的,问题必须在 A* 算法实现中。

此外,它的第一步不同于最优的这一事实是没有意义的:该算法可以正确地执行回溯以在未来得到正确的解决方案路径。所有打开的节点都是下一步的候选,而不仅仅是当前节点的子节点。

【讨论】:

  • 感谢您的回答 - 我什至会说,虽然 A* 实现是正确的,但似乎我计算的东西既不是移动计数也不是路径访问计数。该算法实际上现在可以正确地解决所有 NxN 难题,并正确检测出不可行的难题。我将很快更新我的原始帖子并提供一些代码,以便我们可以发现困扰我好几天的错误。
猜你喜欢
  • 2012-06-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-05
相关资源
最近更新 更多