- c - 在位数组中找到第一个零
- linux - Unix 显示有关匹配两种模式之一的文件的信息
- 正则表达式替换多个文件
- linux - 隐藏来自 xtrace 的命令
我找到了这个算法 here .
我有一个问题,我似乎无法理解如何设置和传递我的启发式函数。
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 个参数,以便我可以将曼哈顿估计传递给它?这意味着第 4 个参数将如下所示:
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));
}
最佳答案
好问题。我同意这篇文章令人困惑。我已对其进行更新以解决您的问题。
首先,回答您提出的问题:您是否应该修改给定的代码以采用不同的功能?如果您愿意,当然可以,但您当然不必这样做。我的建议是传递算法想要的函数,因为这是它需要的函数。为什么要传递算法不需要的信息?
怎么办?
我给出的 A* 算法有两个函数。
第一个函数给出两个给定相邻节点之间的精确距离。
第二个函数给出给定节点和目标节点之间的估计距离。
这是你没有的第二个功能。
如果您有一个函数可以给出两个给定节点之间的估计距离,并且您需要一个可以给出给定节点之间的估计距离的函数em> 和 目标节点 然后构建该函数:
Func<Node, Node, double> estimatedDistanceBetweenTwoNodes = whatever;
Func<Node, double> estimatedDistanceToDestination = n=>estimatedDistanceBetweenTwoNodes(n, destination);
你就完成了。现在您拥有了所需的功能。
这种通过将其中一个参数固定为某个值来将双参数函数变成单参数函数的技术称为“偏函数应用”,它在函数式编程中极为常见。
都清楚了吗?
现在讨论第二个更严重的问题。正如我在我的文章中所述,算法的正确运行取决于估计函数是否保守。你能保证曼哈顿距离永远不会高估吗?这似乎不太可能。如果网格中的任何地方都有一条“对角线”街道,那么曼哈顿距离会高估两点之间的最佳距离,A* 算法将找不到它。大多数人对 A* 算法使用欧氏距离(也称为 L2 范数),因为根据定义,两点之间的最短距离不会被高估。 你为什么使用曼哈顿距离?我很困惑你为什么认为这是个好主意。
关于c# - A-star (A*) 的曼哈顿启发式函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4532528/
我是一名优秀的程序员,十分优秀!