跳转到内容

启发式搜索:修订间差异

来自代码酷
Admin留言 | 贡献
Page creation by admin bot
 
Admin留言 | 贡献
Page update by admin bot
 
第1行: 第1行:
{{DISPLAYTITLE:启发式搜索}}
{{DISPLAYTITLE:启发式搜索}}
'''启发式搜索'''(Heuristic Search)是一种利用问题领域的额外信息(即启发式函数)来引导搜索方向的算法,旨在提高搜索效率并减少不必要的计算。与盲目搜索(如广度优先搜索、深度优先搜索)不同,启发式搜索通过评估当前状态到目标的“潜力”来优化路径选择,常用于解决复杂问题(如路径规划、游戏AI、优化问题等)。 


== 介绍 ==
== 核心概念 ==
'''启发式搜索'''(Heuristic Search)是一种在[[回溯与分支限界]]算法中广泛使用的优化技术,它通过引入'''启发式函数'''(Heuristic Function)来指导搜索方向,从而减少不必要的计算,提高搜索效率。与盲目搜索(如[[深度优先搜索]]或[[广度优先搜索]])不同,启发式搜索利用问题领域的额外信息(即启发式信息)来估计当前状态到目标状态的“距离”,从而优先探索更有可能接近目标的路径。
启发式搜索的核心是'''启发式函数'''(Heuristic Function),记作 <math>h(n)</math>,用于估计从当前节点 <math>n</math> 到目标节点的最低成本。该函数的设计直接影响算法的效率和准确性。 


启发式搜索常用于以下场景:
=== 常见启发式搜索算法 === 
* [[路径规划]](如A*算法)
* '''A*算法''':结合路径成本 <math>g(n)</math> 和启发式函数 <math>h(n)</math>,选择 <math>f(n) = g(n) + h(n)</math> 最小的节点扩展。 
* [[人工智能]]中的问题求解(如博弈树搜索)
* '''贪婪最佳优先搜索'''(Greedy Best-First Search):仅依赖启发式函数 <math>h(n)</math>,优先扩展“看似最优”的节点。 
* [[组合优化]]问题(如旅行商问题)
* '''迭代加深A*'''(IDA*):通过动态调整 <math>f(n)</math> 的阈值来优化内存使用。 


== 核心概念 ==
== 数学基础 ==
=== 启发式函数 ===
启发式函数需满足以下条件: 
启发式函数 <math>h(n)</math> 用于估计从当前节点 <math>n</math> 到目标节点的'''最低成本'''。该函数必须满足以下条件:
* '''可采纳性'''(Admissibility):<math>h(n)</math> 不得高估实际成本,即 <math>h(n) \leq h^*(n)</math><math>h^*(n)</math> 为真实成本)。 
* '''可采纳性'''(Admissibility):<math>h(n)</math> 不能高估实际成本,即 <math>h(n) \leq h^*(n)</math>,其中 <math>h^*(n)</math> 是真实成本。
* '''一致性'''(Consistency):对于任意相邻节点 <math>n</math> 和 <math>m</math>,满足 <math>h(n) \leq c(n, m) + h(m)</math><math>c(n, m)</math> 为边成本)。 
* '''一致性'''(Consistency):对于任意相邻节点 <math>n</math> 和 <math>n'</math><math>h(n) \leq c(n, n') + h(n')</math>,其中 <math>c(n, n')</math> 是从 <math>n</math> 到 <math>n'</math> 的实际成本。


=== 常见启发式搜索算法 ===
== 代码示例 ==
* '''[[贪婪最佳优先搜索]]'''(Greedy Best-First Search):仅依赖启发式函数 <math>h(n)</math> 选择下一个节点。
以下为 Python 实现的 A* 算法示例,解决网格路径规划问题: 
* '''[[A*算法]]''':结合实际成本 <math>g(n)</math> 和启发式函数 <math>h(n)</math>,使用 <math>f(n) = g(n) + h(n)</math> 作为优先级。
* '''[[IDA*算法]]''':迭代加深的A*算法,节省内存。


== 代码示例 ==
<syntaxhighlight lang="python"> 
以下是一个使用A*算法解决8数码问题(8-Puzzle)的Python示例:
import heapq 


<syntaxhighlight lang="python">
def heuristic(a, b): 
import heapq
    # 曼哈顿距离作为启发式函数 
    return abs(a[0] - b[0]) + abs(a[1] - b[1]) 


def heuristic(state, target):
def a_star(grid, start, goal):
     """曼哈顿距离启发式函数"""
     neighbors = [(0, 1), (1, 0), (0, -1), (-1, 0)
    distance = 0
    open_set = []
    for i in range(3):
    heapq.heappush(open_set, (0, start))
        for j in range(3):
    came_from = {} 
            if state[i][j] != 0:
    g_score = {start: 0} 
                x, y = divmod(target[state[i][j]], 3)
    f_score = {start: heuristic(start, goal)
                distance += abs(x - i) + abs(y - j)
    return distance


def a_star(start, target):
    while open_set: 
    open_set = []
        _, current = heapq.heappop(open_set)
    heapq.heappush(open_set, (0 + heuristic(start, target), 0, start))
        if current == goal:
    came_from = {}
            path = []
    g_score = {tuple(map(tuple, start)): 0}
            while current in came_from: 
                path.append(current)
                current = came_from[current] 
            return path[::-1] 


    while open_set:
        for dx, dy in neighbors:
        _, current_g, current = heapq.heappop(open_set)
            neighbor = (current[0] + dx, current[1] + dy) 
        if current == target:
            if 0 <= neighbor[0] < len(grid) and 0 <= neighbor[1] < len(grid[0]) and grid[neighbor[0]][neighbor[1]] == 0: 
            return reconstruct_path(came_from, current)
                tentative_g_score = g_score[current] + 1 
                if neighbor not in g_score or tentative_g_score < g_score[neighbor]: 
                    came_from[neighbor] = current
                    g_score[neighbor] = tentative_g_score 
                    f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal) 
                    heapq.heappush(open_set, (f_score[neighbor], neighbor))
    return None 


        for neighbor in get_neighbors(current):
# 示例输入:0表示可通行,1表示障碍物 
            tentative_g = current_g + 1
grid =
            if tentative_g < g_score.get(tuple(map(tuple, neighbor)), float('inf')):
    [0, 0, 0, 0], 
                came_from[tuple(map(tuple, neighbor))] = tuple(map(tuple, current))
    [1, 1, 0, 1], 
                g_score[tuple(map(tuple, neighbor))] = tentative_g
    [0, 0, 0, 0] 
                f_score = tentative_g + heuristic(neighbor, target)
                heapq.heappush(open_set, (f_score, tentative_g, neighbor))
start = (0, 0)
    return None
goal = (2, 3)
</syntaxhighlight>
print(a_star(grid, start, goal)) # 输出:[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (2, 3)
</syntaxhighlight>


'''输入与输出示例'''
== 实际应用 == 
* 初始状态:<code>[[1, 2, 3], [4, 0, 6], [7, 5, 8]]</code>
1. '''游戏AI''':如《星际争霸》中的单位寻路。 
* 目标状态:<code>[[1, 2, 3], [4, 5, 6], [7, 8, 0]]</code>
2. '''机器人导航''':无人机避开障碍物到达目标点。 
* 输出:返回从初始状态到目标状态的最短移动序列。
3. '''自然语言处理''':机器翻译中搜索最优译文序列。 


== 实际应用案例 ==
== 性能优化与权衡 ==
=== 路径规划 ===
* '''启发式函数设计''':更好的启发式能显著减少搜索空间(如欧几里得距离比曼哈顿距离更精确)。 
在导航软件(如Google Maps)中,A*算法用于计算最短路径。启发式函数通常选择两点之间的直线距离(欧几里得距离),因其满足可采纳性。
* '''内存限制''':IDA* 适用于内存紧张的场景,但可能重复计算。 


<mermaid>
== 可视化示例 == 
graph LR
<mermaid>
     A[起点] -->|实际道路距离| B[节点1]
graph TD 
     B -->|h(n)=直线距离| C[目标点]
     A[Start] -->|g=1| B
</mermaid>
    A -->|g=1.4| C 
     B -->|g=2| D 
    C -->|g=2| D 
    D -->|h=0| Goal 
    style A fill:#f9f 
    style Goal fill:#f66 
</mermaid>
图中数字为 <math>g(n)</math>(路径成本)和 <math>h(n)</math>(启发式估计),A* 会选择总成本 <math>f(n)</math> 最低的路径。 


=== 游戏AI ===
== 总结 ==
在策略游戏中,启发式搜索用于优化单位移动或资源分配。例如,《星际争霸》中的AI使用启发式函数评估地图区域的战略价值。
启发式搜索通过智能地选择扩展节点,显著提升了搜索效率。理解启发式函数的设计原则和算法特性(如 A* 的最优性)是掌握该技术的关键。实际应用中需根据问题特点权衡速度与精度。
 
== 数学基础 ==
启发式搜索的性能依赖于启发式函数的质量。定义'''分支因子''' <math>b</math> 和'''有效深度''' <math>d</math>,则A*算法的时间复杂度为 <math>O(b^d)</math>,但实际中因启发式函数的剪枝效果远优于盲目搜索。
 
最优性条件:
* 如果 <math>h(n)</math> 可采纳,则A*算法返回最优解。
* 如果 <math>h(n)</math> 一致,则A*算法高效且无需重复处理节点。
 
== 进阶主题 ==
* '''加权A*算法''':引入权重 <math>w</math> 平衡 <math>g(n)</math> 和 <math>h(n)</math>,即 <math>f(n) = g(n) + w \cdot h(n)</math>。
* '''实时启发式搜索''':适用于动态环境,如机器人实时避障。
 
== 总结 ==
启发式搜索通过智能地选择搜索方向显著提升算法效率,但其效果高度依赖启发式函数的设计。开发者需根据具体问题设计合理的启发式函数,以平衡最优性和计算成本。


[[Category:计算机科学]]
[[Category:计算机科学]]
[[Category:数据结构与算法]]
[[Category:面试技巧]]
[[Category:回溯与分支限界]]
[[Category:搜索算法]]

2025年5月12日 (一) 00:23的最新版本

启发式搜索(Heuristic Search)是一种利用问题领域的额外信息(即启发式函数)来引导搜索方向的算法,旨在提高搜索效率并减少不必要的计算。与盲目搜索(如广度优先搜索、深度优先搜索)不同,启发式搜索通过评估当前状态到目标的“潜力”来优化路径选择,常用于解决复杂问题(如路径规划、游戏AI、优化问题等)。

核心概念[编辑 | 编辑源代码]

启发式搜索的核心是启发式函数(Heuristic Function),记作 h(n),用于估计从当前节点 n 到目标节点的最低成本。该函数的设计直接影响算法的效率和准确性。

常见启发式搜索算法[编辑 | 编辑源代码]

  • A*算法:结合路径成本 g(n) 和启发式函数 h(n),选择 f(n)=g(n)+h(n) 最小的节点扩展。
  • 贪婪最佳优先搜索(Greedy Best-First Search):仅依赖启发式函数 h(n),优先扩展“看似最优”的节点。
  • 迭代加深A*(IDA*):通过动态调整 f(n) 的阈值来优化内存使用。

数学基础[编辑 | 编辑源代码]

启发式函数需满足以下条件:

  • 可采纳性(Admissibility):h(n) 不得高估实际成本,即 h(n)h*(n)h*(n) 为真实成本)。
  • 一致性(Consistency):对于任意相邻节点 nm,满足 h(n)c(n,m)+h(m)c(n,m) 为边成本)。

代码示例[编辑 | 编辑源代码]

以下为 Python 实现的 A* 算法示例,解决网格路径规划问题:

  
import heapq  

def heuristic(a, b):  
    # 曼哈顿距离作为启发式函数  
    return abs(a[0] - b[0]) + abs(a[1] - b[1])  

def a_star(grid, start, goal):  
    neighbors = [(0, 1), (1, 0), (0, -1), (-1, 0)]  
    open_set = []  
    heapq.heappush(open_set, (0, start))  
    came_from = {}  
    g_score = {start: 0}  
    f_score = {start: heuristic(start, goal)}  

    while open_set:  
        _, current = heapq.heappop(open_set)  
        if current == goal:  
            path = []  
            while current in came_from:  
                path.append(current)  
                current = came_from[current]  
            return path[::-1]  

        for dx, dy in neighbors:  
            neighbor = (current[0] + dx, current[1] + dy)  
            if 0 <= neighbor[0] < len(grid) and 0 <= neighbor[1] < len(grid[0]) and grid[neighbor[0]][neighbor[1]] == 0:  
                tentative_g_score = g_score[current] + 1  
                if neighbor not in g_score or tentative_g_score < g_score[neighbor]:  
                    came_from[neighbor] = current  
                    g_score[neighbor] = tentative_g_score  
                    f_score[neighbor] = g_score[neighbor] + heuristic(neighbor, goal)  
                    heapq.heappush(open_set, (f_score[neighbor], neighbor))  
    return None  

# 示例输入:0表示可通行,1表示障碍物  
grid = [  
    [0, 0, 0, 0],  
    [1, 1, 0, 1],  
    [0, 0, 0, 0]  
]  
start = (0, 0)  
goal = (2, 3)  
print(a_star(grid, start, goal))  # 输出:[(0, 0), (0, 1), (0, 2), (1, 2), (2, 2), (2, 3)]

实际应用[编辑 | 编辑源代码]

1. 游戏AI:如《星际争霸》中的单位寻路。 2. 机器人导航:无人机避开障碍物到达目标点。 3. 自然语言处理:机器翻译中搜索最优译文序列。

性能优化与权衡[编辑 | 编辑源代码]

  • 启发式函数设计:更好的启发式能显著减少搜索空间(如欧几里得距离比曼哈顿距离更精确)。
  • 内存限制:IDA* 适用于内存紧张的场景,但可能重复计算。

可视化示例[编辑 | 编辑源代码]

graph TD A[Start] -->|g=1| B A -->|g=1.4| C B -->|g=2| D C -->|g=2| D D -->|h=0| Goal style A fill:#f9f style Goal fill:#f66

图中数字为

g(n)

(路径成本)和

h(n)

(启发式估计),A* 会选择总成本

f(n)

最低的路径。

总结[编辑 | 编辑源代码]

启发式搜索通过智能地选择扩展节点,显著提升了搜索效率。理解启发式函数的设计原则和算法特性(如 A* 的最优性)是掌握该技术的关键。实际应用中需根据问题特点权衡速度与精度。