A*算法 一看便懂(Python)

最佳优先搜索算法
工作原理:依据某种代价对节点进行排序,并优先扩展代价低的节点。
优先访问代价小的节点:
1.找出最优
2.更快找出目标节点
注:一致代价搜索(UCS算法)是最佳优先搜索的特例;A*算法也是最佳优先搜索算法的特例。

贪心最佳优先搜索
启发函数h(n):估算节点n到目标节点的代价
h(n)的限制:非负;不能高估
代价函数:f(n)=h(n),g(n)≡0
工作原理:试图从局部最优达到总体最优
弊端:在一些情况下,局部最优并不能达到总体最优,例如:迷宫算法

A * 搜索算法
~前言:Dijkstra的算法很好地找到了最短的路径,但是却浪费了时间在没有希望的方向上进行探索。贪婪最佳优先搜索在有希望的方向上进行探索,但可能找不到最短的路径。A * 算法结合了这两种算法。Dijkstra的算法计算到起点的距离。贪婪最佳优先搜索估计到目标点的距离。A * 使用的是这两个距离的和。

~工作原理:f(n)=h(n)+g(n),g(n):开始节点到n节点的实际路径代价;h(n):估算节点n到目标节点的代价。故,A*算法首先扩展f(n)值最小的节点

~对启发函数的2个限制:
1.h(n)必须可接受或具有可接受性
2.h(n)必须是一致的或具有一致性或单调性

~注:单调一致的启发函数一定是可接受的

~优点:一个节点被访问后不会再被访问。完备性和最优性,在满足单调一致条件时,具有效率最优性。

~缺点:
1.对于相当多的问题,在搜索空间中处于目标等值线以内的节点数量,仍然与解路径的长度呈指数级增长。
2.A * 算法在内存中保存了所有已生成的节点,A *算法常常在问题求解之前就已经耗尽了内存。
不适用情况:对于很多大规模搜索

~如何找启发函数:
子问题的最优代价可以作为启发函数,正方形网格适合用曼哈顿距离作为启发函数
1.允许四个方向移动的正方形网格,启发函数适合用曼哈顿距离。
2.允许八个方向移动的正方形网格,启发函数适合用对角线距离
3.允许各个方向移动的正方形网格,可以试试欧式距离

下面是将A*算法应用到8数码(Puzzles8)问题上的流程:
sum(h(n))=|目标点.row-该点.row|+|目标点.col-该点.col|,根据算出的f(n)进行优先级排序,选择出优先级高的作为下一步
1.在这里插入图片描述
2.在这里插入图片描述
3.在这里插入图片描述
4.在这里插入图片描述
5.在这里插入图片描述




24.
在这里插入图片描述
下面是对应的代码:

# -*- coding: utf-8 -*-
"""
Created on Sun Oct 21 15:25:43 2018

@author: duxiaoqin
Functions:
    (1)
  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,让我来介绍一下A*算法的代码结构。A*算法是一种启发式搜索算法,主要用于寻找图中的最短路径。主要分为以下几个模块: 1. Graph类:定义了图的结构,包括节点和边 2. Node类:表示图中的一个节点,记录了节点的坐标和与该节点相关的边 3. Edge类:表示图中的一条边,记录了边的起点、终点和权重 4. AStar类:实现了A*算法,包括启发函数、搜索函数和路径生成函数 现在,我们需要添加一个模块,用于用户操作说明。这个模块可以在用户第一次使用A*算法时,自动输出一些使用说明,告诉用户如何使用算法。 代码如下: ```python # 用户操作说明模块 def user_guide(): """输出用户操作说明""" print("欢迎使用A*算法!") print("A*算法是一种启发式搜索算法,用于寻找图中的最短路径。") print("请确保输入的起点和终点坐标在图中存在。") print("如果您想退出程序,请输入'exit'或者'quit'。") print("祝您使用愉快!\n") ``` 这个模块很简单,只是输出了一些使用说明。我们可以在主函数中调用这个函数,让它在用户第一次使用A*算法时自动输出。 接下来,我们需要对代码进行注释,让代码更易读,方便其他人理解和修改。 代码注释如下: ```python # 定义Graph类 class Graph: def __init__(self, nodes, edges): self.nodes = nodes # 节点列表 self.edges = edges # 边列表 # 定义Node类 class Node: def __init__(self, x, y): self.x = x # x坐标 self.y = y # y坐标 self.edges = [] # 与该节点相关的边 def add_edge(self, edge): """添加一条与该节点相关的边""" self.edges.append(edge) def __str__(self): return f"({self.x}, {self.y})" # 定义Edge类 class Edge: def __init__(self, start, end, weight): self.start = start # 起点 self.end = end # 终点 self.weight = weight # 权重 # 定义AStar类 class AStar: def __init__(self, graph, heuristic): self.graph = graph # 图 self.heuristic = heuristic # 启发函数 def search(self, start, end): """A*搜索函数""" # 初始化起点和终点的g值和f值 start.g = 0 start.f = self.heuristic(start, end) # 初始化open和closed列表 open_list = [start] closed_list = [] while open_list: # 从open列表中选出f值最小的节点 current_node = min(open_list, key=lambda x: x.f) # 如果当前节点是终点,生成路径并返回 if current_node == end: return self.generate_path(start, end) # 将当前节点从open列表中移除,加入closed列表 open_list.remove(current_node) closed_list.append(current_node) # 遍历当前节点的所有邻居节点 for edge in current_node.edges: neighbor = edge.end # 如果邻居节点已经在closed列表中,跳过 if neighbor in closed_list: continue # 计算邻居节点的g值和f值 tentative_g = current_node.g + edge.weight tentative_f = tentative_g + self.heuristic(neighbor, end) # 如果邻居节点不在open列表中,将其加入 if neighbor not in open_list: neighbor.g = tentative_g neighbor.f = tentative_f neighbor.parent = current_node open_list.append(neighbor) # 否则,更新邻居节点的g值和f值 else: if tentative_g < neighbor.g: neighbor.g = tentative_g neighbor.f = tentative_f neighbor.parent = current_node # 如果open列表为空,无法找到路径,返回空 return None def generate_path(self, start, end): """生成路径""" path = [] current_node = end while current_node != start: path.append(current_node) current_node = current_node.parent path.append(start) return path[::-1] # 启发函数 def manhattan_distance(node1, node2): """曼哈顿距离""" return abs(node1.x - node2.x) + abs(node1.y - node2.y) # 用户操作说明模块 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值