我认识到您可能还从其他答案中获得了要点,但这是一个有趣的问题,我觉得自己需要做一些Python编码。这是我的面向对象方法。缩进定义范围。
图表示
可以轻松地将图形存储为键,值字典,其中键是房间ID,值是它引向的房间的数组。
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
座席接口
首先,我们应该考虑代理应该能够从环境中学到什么信息,以及它应该执行的操作。这将简化对算法的思考。
在这种情况下,代理应该能够查询环境以获取其所在房间的ID,它应该能够获取其所在房间的门数(请注意,这不是该房间的ID。门通向!),他应该能够通过指定门索引在门中移动。代理知道的任何其他事情都必须由代理自己解决。
class AgentInterface(object):
def __init__(self, map, starting_room):
self.map = map
self.current_room = starting_room
def get_door_count(self):
return len(self.map[self.current_room])
def go_through_door(self, door):
result = self.current_room = self.map[self.current_room][door]
return result
代理商知识
当业务代表第一次进入地图时,它只知道房间中的门数量以及当前所在房间的ID。我需要创建一个结构来存储业务代表已经了解的信息,例如尚未访问过的门。穿过,通往那扇门的地方已经穿过。
此类表示有关单个房间的信息。我选择将未访问的门存储为,将已访问的门存储set
为dictionary
,其中键是门ID,值是它通往的房间的ID。
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
代理算法
座席每次进入会议室时,都会在其知识词典中搜索有关该会议室的信息。如果该房间没有任何条目,那么它将创建一个新条目RoomKnowledge
并将其添加到其知识词典中。
它检查当前房间是否是目标房间,如果是,则返回。
如果在这个房间中没有我们没有去过的门,我们会穿过门并存放它通往的地方。然后,我们继续循环。
如果没有未访问的门,我们会回头浏览我们访问过的房间,以找到一扇未访问的门。
在Agent
类继承的AgentInterface
类。
class Agent(AgentInterface):
def find_exit(self, exit_room_id):
knowledge = { }
room_history = [] # For display purposes only
history_stack = [] # Used when we need to backtrack if we've visited all the doors in the room
while True:
room_knowledge = knowledge.setdefault(self.current_room, RoomKnowledge(self.get_door_count()))
room_history.append(self.current_room)
if self.current_room==exit_room_id:
return room_history
if len(room_knowledge.unvisited_doors)==0:
# I have destination room id. I need door id:
door = find_key(room_knowledge.visited_doors, history_stack.pop())
self.go_through_door(door)
else:
history_stack.append(self.current_room)
# Enter the first unopened door:
opened_door = room_knowledge.unvisited_doors.pop()
room_knowledge.visited_doors[opened_door]=self.go_through_door(opened_door)
配套功能
我必须编写一个函数,该函数将在字典中找到一个给定值的键,因为回溯时,我们知道我们要到达的房间的ID,但不知道要使用哪个门。
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
测试中
我在上面给出的地图中测试了开始/结束位置的所有组合。对于每种组合,它都会打印出访问过的房间。
for start in range(1, 7):
for exit in range(1, 7):
print("start room: %d target room: %d"%(start,exit))
james_bond = Agent(map, start)
print(james_bond.find_exit(exit))
笔记
回溯不是很有效-在最坏的情况下,它可能会遍历每个房间到达相邻的房间,但是回溯是相当少见的-在上述测试中,回溯仅会回溯3次。我避免放置异常处理以保持代码简洁。我对Python的任何评论表示赞赏: