最短路(三) A star Heuristics

本文详细介绍了A*搜索算法的工作原理,包括算法的标记、计算方式以及选择节点的标准。通过实例阐述了算法的执行过程,并讨论了其在不同heuristic函数选择下的准确性。A*算法在heuristic满足特定条件时(如一致性或可接纳性)能保证找到最优解。此外,还提到了当节点被多次探索时,如何保证找到的路径是最优的。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

最短路(三) A star Heuristics


属于一种best-first search,通过不断选择当前预期距离最小的点来实现。

参考:
http://www.cs.cmu.edu/~cga/ai-course/astar.pdf
https://en.wikipedia.org/wiki/A*_search_algorithm

标记

g ( n ) = d i s t a n c e [ s t a r t ] [ n ] g(n) = distance[start][n] g(n)=distance[start][n], (当前计算得到的准确值)
h ( n ) = d i s t a n c e [ n ] [ e n d ] h(n) = distance[n][end] h(n)=distance[n][end] (由heuristic函数决定)
f ( n ) = g ( n ) + h ( n ) f(n) = g(n) + h(n) f(n)=g(n)+h(n)

算法

  1. 每轮取 f ( n ) f(n) f(n)最小的点
  2. 遍历neighbor,如果当前经过 n n n到neighbor的路径更优,更新他们的 g , f g,f gf

代码

public class Astar {

    public static void main(String[] args) {
        double[][] graph = new double[6][6];
        for (int i = 0; i < 6; i++) {
            for (int j = 0; j < 6; j++) {
                graph[i][j] = Double.MAX_VALUE;
            }
        }
        graph[0][1] = 1;
        graph[0][2] = 1;
        graph[2][3] = 1;
        graph[1][3] = 0.5;
        graph[3][4] = 1;
        graph[4][5] = 7;
        int[] h = new int[] {8, 7, 3, 2, 1, 0};
        for (int i : astar(0, 5, graph, h)) {
            System.out.print(i + " ");
        }
    }

    /**
     *
     * @param start start vertex
     * @param end end vertex
     * @param graph adjacency matrix, value as edge weight
     * @param h heuristics
     * @return shortest path from start to end
     */
    public static List<Integer> astar(int start, int end, double[][] graph, int[] h) {

        double[] g = new double[graph.length];
        Arrays.fill(g, Double.MAX_VALUE);
        g[start] = 0;

        double[] f = new double[graph.length];
        Arrays.fill(f, Double.MAX_VALUE);
        f[start] = h[start];

        int[] parent = new int[graph.length]; // to reconstruct path
        Arrays.fill(parent, -1);

        PriorityQueue<Integer> pq = new PriorityQueue<>((o1, o2) -> Double.compare(f[o1], f[o2]));
        pq.add(start);

        while(!pq.isEmpty()) {
            int current = pq.poll();
            if (current == end) {
                return reconstruct(parent, current);
            }
            System.out.println("current " + current + " f " + f[current]);
            for (int i = 0; i < graph.length; i++) { // loop through the neighbors
                if (graph[current][i] != Double.MAX_VALUE) { // connected
                    double temp = g[current] + graph[current][i];
                    if (temp < g[i] && g[current] != Double.MAX_VALUE) { // this path is shorter
                        parent[i] = current;
                        g[i] = temp;
                        f[i] = g[i] + h[i];
                    }
                    if (!pq.contains(i)) {
                        pq.add(i);
                    }
                }
            }
        }

        return null; // no path available
    }

    public static List<Integer> reconstruct(int[] parent, int current) {
        List<Integer> list = new LinkedList<>();
        while (current != -1) {
            list.add(0, current);
            current = parent[current];
        }
        return list;
    }
}
Output: 
current 0 f 8.0
current 2 f 4.0
current 3 f 4.0
current 4 f 4.0
current 1 f 8.0
current 3 f 3.5
current 4 f 3.5
0 1 3 4 5 

例子

A star Heuristics

准确性

在这里插入图片描述
A*的准确性依赖于heuristic的选择。在两个条件下保证最优。

  1. Consistency(较强)
    对任意边 ( x , y ) (x, y) (x,y),有 h ( x ) ≤ d ( x , y ) + h ( y ) h(x) ≤ d(x, y) + h(y) h(x)d(x,y)+h(y).
    理解: 此时相当于 J o h n s o n ′ s A l g o r i t h m Johnson's Algorithm JohnsonsAlgorithm,是对每条边重新分配权重 d ′ ( x , y ) = d ( x , y ) + h ( y ) − h ( x ) d'(x, y) = d(x, y) + h(y) - h(x) d(x,y)=d(x,y)+h(y)h(x)使之非负,然后使用 D i j k s t r a Dijkstra Dijkstra保证正确性
  2. Admissible(较弱)
    对任意点有 h ( n ) < = h ∗ ( n ) h(n) <= h^{*}(n) h(n)<=h(n). h ∗ ( n ) h^{*}(n) h(n)是从 n n n到end的最优解。
    反证:
    假设存在该算法结果 f ( e n d ) > f ∗ = h ∗ ( s t a r t ) = 最 优 解 f(end) > f* = h^{*}(start) = 最优解 f(end)>f=h(start)=,假设 n n n在最优路径上,由算法结束条件得 f ( n ) > f ( e n d ) f(n) > f(end) f(n)>f(end)
    f ( n ) = g ( n ) + h ( n ) = g ∗ ( n ) + h ( n ) ( n 在 最 优 路 径 上 ) < = g ∗ ( n ) + h ∗ ( n ) ( A d m i s s i b l e ) = f ∗ f ∗ > = f ( n ) > = f ( e n d ) ( c o n t r a d i c t i o n ) f(n) = g(n) + h(n) \\ = g^{*}(n) + h(n) (n在最优路径上) \\ <= g^{*}(n) + h^{*}(n) (Admissible)\\ = f^{*} \\ f^{*} >= f(n) >= f(end) (contradiction) f(n)=g(n)+h(n)=g(n)+h(n)n)<=g(n)+h(n)(Admissible)=ff>=f(n)>=f(end)(contradiction)

注:if a node is reached by one path, removed from openSet, and subsequently reached by a cheaper path, it will be added to openSet again. This is essential to guarantee that the path returned is optimal if the heuristic function is admissible but not consistent. If the heuristic is consistent, when a node is removed from openSet the path to it is guaranteed to be optimal so the test ‘tentative_gScore < gScore[neighbor]’ will always fail if the node is reached again.
和例子中点4的情况相同

heuristics{}通常是指启发式算法中的一个结构,它用于定义一组规则、策略或近似方法来解决特定问题。这些规则不是保证优解,而是为了提高搜索效率,在面对复杂或不确定环境时提供一种经验性的解决方案。在编程中,特别是在搜索、优化或人工智能领域,比如在游戏中寻找路径、机器学习中的推荐系统,可能会使用heuristics{}来指导决策。 例如,在A*寻路算法中,heuristics函数(也称启发函数)估计从当前节点到目标节点的短距离,这个估计值会作为搜索算法选择下一个节点的依据。在Python的某个框架中,你可能会看到类似这样的定义: ```python def heuristic(current_node, target_node): return manhattan_distance(current_node.position, target_node.position) # 使用heuristics作为部分计算A*算法的关键 def a_star_search(graph, start, goal): open_list = [start] closed_list = [] h = heuristics while open_list: current = min(open_list, key=lambda node: node.f_cost) if current == goal: return path_from(start, current) open_list.remove(current) closed_list.append(current) for neighbor in graph.neighbors(current): if neighbor not in closed_list: tentative_g_score = current.g_score + graph.cost(current, neighbor) if neighbor not in open_list or tentative_g_score < neighbor.g_score: neighbor.g_score = tentative_g_score neighbor.h_score = h(neighbor, goal) neighbor.parent = current open_list.append(neighbor) return None ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值