A-star (A*) 的曼哈顿启发式函数
我发现了这个算法此处。
我有一个问题,我似乎无法理解如何设置和传递我的启发式函数。
static public Path<TNode> AStar<TNode>(TNode start, TNode destination,
Func<TNode, TNode, double> distance,
Func<TNode, double> estimate) where TNode : IHasNeighbours<TNode>
{
var closed = new HashSet<TNode>();
var queue = new PriorityQueue<double, Path<TNode>>();
queue.Enqueue(0, new Path<TNode>(start));
while (!queue.IsEmpty)
{
var path = queue.Dequeue();
if (closed.Contains(path.LastStep))
continue;
if (path.LastStep.Equals(destination))
return path;
closed.Add(path.LastStep);
foreach (TNode n in path.LastStep.Neighbours)
{
double d = distance(path.LastStep, n);
var newPath = path.AddStep(n, d);
queue.Enqueue(newPath.TotalCost + estimate(n), newPath);
}
}
return null;
}
正如您所看到的,它接受 2 个函数:距离函数和估计函数。
使用曼哈顿启发式距离函数,我需要采用 2 个参数。我是否需要修改他的源并将其更改为接受 TNode 的 2 个参数,以便我可以将曼哈顿估计传递给它?这意味着第四个参数将如下所示:
Func<TNode, TNode, double> estimate) where TNode : IHasNeighbours<TNode>
并将估计函数更改为:
queue.Enqueue(newPath.TotalCost + estimate(n, path.LastStep), newPath);
我的曼哈顿函数是:
private float manhattanHeuristic(Vector3 newNode, Vector3 end)
{
return (Math.Abs(newNode.X - end.X) + Math.Abs(newNode.Y - end.Y));
}
I found this algorithm here.
I have a problem, I cant seem to understand how to set up and pass my heuristic function.
static public Path<TNode> AStar<TNode>(TNode start, TNode destination,
Func<TNode, TNode, double> distance,
Func<TNode, double> estimate) where TNode : IHasNeighbours<TNode>
{
var closed = new HashSet<TNode>();
var queue = new PriorityQueue<double, Path<TNode>>();
queue.Enqueue(0, new Path<TNode>(start));
while (!queue.IsEmpty)
{
var path = queue.Dequeue();
if (closed.Contains(path.LastStep))
continue;
if (path.LastStep.Equals(destination))
return path;
closed.Add(path.LastStep);
foreach (TNode n in path.LastStep.Neighbours)
{
double d = distance(path.LastStep, n);
var newPath = path.AddStep(n, d);
queue.Enqueue(newPath.TotalCost + estimate(n), newPath);
}
}
return null;
}
As you can see, it accepts 2 functions, a distance and a estimate function.
Using the Manhattan Heuristic Distance function, I need to take 2 parameters. Do I need to modify his source and change it to accepting 2 parameters of TNode so I can pass a Manhattan estimate to it? This means the 4th param will look like this:
Func<TNode, TNode, double> estimate) where TNode : IHasNeighbours<TNode>
and change the estimate function to:
queue.Enqueue(newPath.TotalCost + estimate(n, path.LastStep), newPath);
My Manhattan function is:
private float manhattanHeuristic(Vector3 newNode, Vector3 end)
{
return (Math.Abs(newNode.X - end.X) + Math.Abs(newNode.Y - end.Y));
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
好问题。我同意这篇文章令人困惑。我已经更新它来解决你的问题。
首先,回答您提出的问题:您是否应该修改给出的代码以采用不同的功能?如果你愿意,当然可以,但你当然不必这样做。我的建议是传递算法想要的函数,因为那是它需要的函数。为什么要传递算法不需要的信息?
该怎么办呢?
我给出的 A* 算法需要两个函数。
第一个函数给出两个给定相邻节点之间的精确距离。
第二个函数给出给定节点和目标节点之间的估计距离。
这是你没有的第二个功能。
如果您有一个函数可以给出两个给定节点之间的估计距离,并且您需要一个函数来给出给定节点和目标节点然后只需构建该函数:
就完成了。现在您已经拥有了您需要的功能。
这种通过将其中一个参数固定为某个值来将二参数函数转变为单参数函数的技术称为“偏函数应用”,在函数式编程中极为常见。
这一切都清楚了吗?
现在讨论第二个更严重的问题。正如我在文章中所述,算法的正确运行取决于估计函数的保守性。您能否保证曼哈顿距离永远不会高估?这似乎不太可能。如果网格中的任何位置存在“对角线”街道,则曼哈顿距离会高估两点之间的最佳距离,并且 A* 算法将找不到它。大多数人在 A* 算法中使用欧几里得距离(也称为 L2 范数),因为根据定义,两点之间的最短距离并不是高估的。 你为什么使用曼哈顿距离?我很困惑为什么你认为这是一个好主意。
Good question. I agree that the article was confusing. I've updated it to address your question.
First, to answer the question you asked: should you modify the code given to take a different function? If you want, sure, but you certainly don't have to. My advice is to pass the function that the algorithm wants, because that's the function that it needs. Why pass information that the algorithm doesn't need?
How do to that?
The A* algorithm I give takes two functions.
The first function gives the exact distance between two given neighbouring nodes.
The second function gives the estimated distance between a given node and the destination node.
It is the second function that you don't have.
If you have a function that gives the estimated distance between two given nodes and you need a function that gives the estimated distance between a given node and the destination node then just build that function:
And you're done. Now you have the function you need.
This technique of turning a two-parameter function into a one-parameter function by fixing one of the parameters to a certain value is called "partial function application" and it is extremely common in functional programming.
Is that all clear?
Now on to the second and much more serious problem. As I described in my articles, the correct operation of the algorithm is predicated on the estimation function being conservative. Can you guarantee that the Manhattan distance never overestimates? That seems unlikely. If there is a "diagonal" street anywhere in the grid then the Manhattan distance overestimates the optimal distance between two points, and the A* algorithm will not find it. Most people use the Euclidean distance (aka the L2 norm) for the A* algorithm because the shortest distance between two points is by definition not an overestimate. Why are you using the Manhattan distance? I am very confused as to why you think this is a good idea.
是的,您需要修改代码,因为不可能在其中使用带有两个
TNode
参数的estimate
方法。Yes, you'd need to modify the code, as there is no possibilty to fit an
estimate
method in there with twoTNode
parameters.