あなたはおそらく他の答えから要点を理解していると思いますが、それは楽しい質問であり、小さなPythonコーディングを行うように感じました。これが私のオブジェクト指向アプローチです。インデントはスコープを定義します。
グラフ表現
グラフは、キー、ルームディクショナリであるキー、値ディクショナリとして簡単に保存できます。値は、それにつながるルームの配列です。
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
エージェントインターフェース
最初に、エージェントが環境からどのような情報を学習できるか、およびエージェントが実行できる操作について考える必要があります。これにより、アルゴリズムについて簡単に考えることができます。
この場合、エージェントはそれがいる部屋のIDを環境に照会できる必要があります。それは、それがいる部屋のドアの数を取得できるはずです(これは部屋のIDではないことに注意してください) doors lead to!)そして、彼はドアインデックスを指定することでドアを通過できるはずです。エージェントが知っている他のすべては、エージェント自体によって理解する必要があります。
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へのコメントは感謝します:)