曼哈顿距离过度估计并让我发疯

时间:2011-10-24 12:41:52

标签: c algorithm artificial-intelligence path-finding heuristics

我正在使用Manhattan distance实施 a-star算法来解决 8-puzzle (在C中)。它似乎工作得非常好,并且通过了大量的单元测试但是在一个案例中找不到最短路径(它找到了27个步骤而不是25个步骤)。

当我将启发式函数更改为Hamming distance时,它会找到25个步骤。 当我使曼哈顿距离函数返回实际成本的一半时,还可以找到25个步骤。

这就是为什么我认为这个问题存在于曼哈顿距离函数的某个地方并且过度估算成本(因此不可接受)。我想也许在C程序中出现了其他问题,所以我写了一个Python脚本来测试和验证曼哈顿距离函数的输出,它们都产生完全相同的结果。

我真的很困惑,因为启发式功能似乎是唯一的失败点,它似乎同时是正确的。

8-puzzle start goal

您可以尝试this solver并将拼贴顺序设置为“2,6,1,0,7,8,3,5,4” 选择算法曼哈顿距离,它可以找到25个步骤。 现在将其更改为曼哈顿距离+线性冲突,它会找到27个步骤。

但我的曼哈顿距离(没有线性冲突)分为27步。

这是我的一般算法:

manhattan_distance = 0
iterate over all tiles
if the tile is not the blank tile:
find the coordinates of this tile on the goal board
manhattan_distance += abs(x - goal_x) + abs(y - goal_y)

我认为如果某些重要部分出现严重错误,则不会通过所有25个以上的测试,因此这可能是某种边缘情况。

这里评论了C:中的曼哈顿距离函数

int ManhattanDistance(Puzzle p, State b){
   State goal = getFinalState(p);
   int size = getSize(b);
   int distance = 0;
   if (getSize(goal) == size){ // both states are the same size
      int i, j;
      for(i=0; i<size; i++){
         for(j=0; j<size; j++){ // iterate over all tiles
            int a = getStateValue(b, i, j); // what is the number on this tile?
            if (a != 'B'){ // if it's not the blank tile
               int final_cordinates[2];
               getTileCoords(goal, a, final_cordinates); // find the coordinates on the other board
               int final_i = final_cordinates[0];
               int final_j = final_cordinates[1];
               distance +=  abs(i - final_i) + abs(j - final_j);
            }
         }
      }
   }
   return distance;
}

请帮帮我。

编辑如评论中所述,可以找到为开放节点提供的代码here

1 个答案:

答案 0 :(得分:6)

问题似乎不在你的启发式函数中,而在于算法本身。从你对问题的描述,以及它只在某些特定情况下发生的事实来看,我相信它与重新打开一个封闭的顶点有关,一旦找到更好的路径就可以了。

在阅读[评论]中提供的代码时,我想我已经理解问题所在的位置,在第20行:

if(getG(current) + 1 < getG(children[i])){

这是错的!您正在检查是否g(current) + 1 < g(children[i]),您确实要检查:f(current) + 1 + h(children[i]) < g(children[i]),因为您要使用children[i]的启发函数检查此值,而不是current
请注意,它与设置f(children[i]) = min{f(children[i]),f(current)+1}相同,然后添加h(children[i])以获取g值。