简单反射型智能体是一类最基础的智能体,它们不维护历史状态,只根据当前感知做出动作决策。下面通过定义、真实案例、代码示例与动手练习,帮助你掌握反射型智能体的核心思想。
3.1 定义:只根据当前感知做反应
- 感知–动作映射:智能体内部只有一组“条件→动作”规则(condition–action rules),没有内部状态或记忆。
- 执行流程:
- 感知环境(Perceive):读取当前传感器输入
- 匹配规则(Match):找到与当前感知相符的规则
- 执行动作(Act):按规则指定的动作作用于环境
- 优点:简单、易实现、计算开销低
- 缺点:无法利用历史信息,容易陷入局部最优或循环
3.2 案例
避障小车
- 感知:前方格子是否有障碍
- 规则:
- 如果前方无障碍,继续前进
- 否则右转 90°
- 应用场景:简单的地面巡逻或清扫机器人
报警系统
- 感知:麦克风检测到的声音强度
- 规则:
- 如果声音 > 阈值(如 0.7),触发报警
- 否则保持静默
- 应用场景:防盗报警、噪声监测
自动门控制
- 感知:红外传感器检测到有人靠近
- 规则:
- 如果有人(距离 < 1m),打开门
- 否则关门
- 应用场景:商场、写字楼出入口
3.3 代码实践
示例 1 – 网格避障小车
# reactive_robot.py
# reactive_robot_visual.py
import matplotlib.pyplot as plt
# 5×5 网格定义:0=空地, 1=障碍
maze = [
[0, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0],
[1, 0, 1, 0, 1],
[0, 0, 0, 0, 0],
]
# 方向向量:上、右、下、左
dirs = [(-1, 0), (0, 1), (1, 0), (0, -1)]
def simulate_fixed(steps=15, start=(2, 4), start_dir=0):
"""
固定右转策略:遇障碍则右转,否则前进
返回经过的路径坐标列表 [(row, col), ...]
"""
pos = list(start)
dir_idx = start_dir
path = [tuple(pos)]
for _ in range(steps):
dr, dc = dirs[dir_idx]
nr, nc = pos[0] + dr, pos[1] + dc
blocked = (
nr < 0 or nr >= len(maze) or
nc < 0 or nc >= len(maze[0]) or
maze[nr][nc] == 1
)
if not blocked:
pos = [nr, nc]
else:
dir_idx = (dir_idx + 1) % 4
path.append(tuple(pos))
return path
if __name__ == "__main__":
# 1. 运行仿真,获取轨迹
path = simulate_fixed()
# 2. 可视化
fig, ax = plt.subplots(figsize=(6, 6))
# 解决中文显示问题
plt.rcParams["font.sans-serif"] = ["SimHei"] # Windows 和 Mac 可能需要不同字体
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
# 绘制障碍格
for r in range(5):
for c in range(5):
if maze[r][c] == 1:
ax.add_patch(plt.Rectangle((c, r), 1, 1, color='gray'))
# 提取坐标:col → x, row → y
rows, cols = zip(*path)
# 绘制轨迹(线+节点)
ax.plot(cols, rows, '-o', label='小车路径')
ax.scatter([cols[0]], [rows[0]], s=100, marker='s', label='起点')
ax.scatter([cols[-1]], [rows[-1]], s=100, marker='*', label='终点')
# 格式化网格
ax.set_xlim(-0.5, 4.5)
ax.set_ylim(-0.5, 4.5)
ax.set_xticks(range(5))
ax.set_yticks(range(5))
ax.invert_yaxis() # 行号从上往下
ax.set_aspect('equal') # 保持方格比例
ax.grid(True)
ax.legend(loc='upper right')
ax.set_title('5×5 网格避障小车轨迹(固定右转策略)')
plt.show()
示例 2 – 声音报警智能体
# alarm_agent.py
import random
import time
THRESHOLD = 0.7
def read_sound_sensor():
# 模拟 0.0~1.0 的声音强度
return random.random()
def alarm_loop(iterations=10):
for i in range(iterations):
level = read_sound_sensor()
# 决策:声音过大报警
if level > THRESHOLD:
print(f"【{i+1}】声级={level:.2f} → 🔔 报警!")
else:
print(f"【{i+1}】声级={level:.2f} → 正常")
time.sleep(0.3)
if __name__ == "__main__":
alarm_loop()
3.4 练习
随机避障
- 在“网格避障小车”基础上:当前方受阻时,不总是“右转”,而是随机选择“左转”或“右转”。
- 观察小车路径的差异,记录前进次数和转向次数。
阈值调优
- 对“声音报警智能体”调整
THRESHOLD
(如 0.3、0.5、0.9),运行 20 次循环,统计报警次数。 - 分析阈值对误报/漏报的影响。
- 对“声音报警智能体”调整
多传感器融合
- 为避障小车增加“边界检测”(模拟左、右侧是否到达墙边)。
- 设计规则:
- 如果前方与侧边都无障碍,优先前进
- 如果前方阻塞且左侧空闲,则左转
- 如果左侧阻塞且前方空闲,则前进
- 否则右转
- 实现并测试。
可视化路径
- 用 Python 的
matplotlib
在 5×5 网格上绘制小车运动轨迹:- 网格用方格图表示,障碍格涂灰
- 每一步在网格中画出小车当前位置
- 为不同策略(固定右转 vs 随机转向)绘制不同颜色路径,对比效果。
参考代码
- 用 Python 的
import random
import matplotlib.pyplot as plt
# 5×5 网格及障碍定义:0=空地, 1=障碍
maze = [
[0, 0, 1, 0, 0],
[0, 1, 0, 1, 0],
[0, 0, 0, 0, 0],
[1, 0, 0, 0, 1],
[0, 0, 0, 1, 0],
]
# 方向向量:上、右、下、左
dirs = [(-1, 0), (0, 1), (1, 0), (0, -1)]
def simulate_fixed(steps=15, start=(2, 4), start_dir=0):
"""
固定右转策略:遇障碍则右转,否则前进
返回经过的路径坐标列表
"""
pos = list(start)
dir_idx = start_dir
path = [tuple(pos)]
for _ in range(steps):
dr, dc = dirs[dir_idx]
nr, nc = pos[0] + dr, pos[1] + dc
blocked = (
nr < 0 or nr >= len(maze) or
nc < 0 or nc >= len(maze[0]) or
maze[nr][nc] == 1
)
if not blocked:
pos = [nr, nc]
else:
dir_idx = (dir_idx + 1) % 4
path.append(tuple(pos))
return path
def simulate_random(steps=15, start=(4, 0), start_dir=0):
"""
随机转向策略:遇障碍时随机左转或右转,否则前进
返回经过的路径坐标列表
"""
pos = list(start)
dir_idx = start_dir
path = [tuple(pos)]
for _ in range(steps):
dr, dc = dirs[dir_idx]
nr, nc = pos[0] + dr, pos[1] + dc
blocked = (
nr < 0 or nr >= len(maze) or
nc < 0 or nc >= len(maze[0]) or
maze[nr][nc] == 1
)
if not blocked:
pos = [nr, nc]
else:
# 随机左转或右转
if random.choice([True, False]):
dir_idx = (dir_idx + 1) % 4
else:
dir_idx = (dir_idx - 1) % 4
path.append(tuple(pos))
return path
# 模拟路径
fixed_path = simulate_fixed()
random_path = simulate_random()
# 可视化路径对比
plt.figure(figsize=(6, 6))
# 解决中文显示问题
plt.rcParams["font.sans-serif"] = ["SimHei"] # Windows 和 Mac 可能需要不同字体
plt.rcParams["axes.unicode_minus"] = False # 解决负号显示问题
# 绘制障碍格
obs = [(r, c) for r in range(5) for c in range(5) if maze[r][c] == 1]
if obs:
obs_rows, obs_cols = zip(*obs)
plt.scatter(obs_cols, obs_rows, marker='s', s=300, label='障碍')
# 绘制固定右转路径
rows_f, cols_f = zip(*fixed_path)
plt.plot(cols_f, rows_f, marker='o', label='固定右转策略')
# 绘制随机转向路径
rows_r, cols_r = zip(*random_path)
plt.plot(cols_r, rows_r, marker='x', label='随机转向策略')
# 格式化图像
plt.gca().invert_yaxis()
plt.xticks(range(5))
plt.yticks(range(5))
plt.grid(True)
plt.legend()
plt.title('5×5 网格避障小车路径对比')
plt.show()
参考输出图案
- 设计一个新场景
- 选一个日常场景(如智能路灯、车道偏离警告),定义感知输入与动作输出,写出至少 5 条规则,并实现成 Python 脚本,验证运行结果。
通过以上案例与练习,你将深刻体会「简单反射型智能体」的原理与局限,为后续引入状态、模型和学习奠定坚实基础。继续动手,才能学得更快、更扎实!