Saya menyadari bahwa Anda mungkin mendapatkan inti dari jawaban lain, tapi itu adalah pertanyaan yang menyenangkan dan saya merasa ingin melakukan sedikit pengkodean Python. Ini adalah pendekatan berorientasi objek saya. Lekukan mendefinisikan ruang lingkup.
Representasi Grafik
Grafik dapat dengan mudah disimpan sebagai kunci, kamus nilai di mana kuncinya adalah id kamar, dan nilainya adalah array dari kamar-kamar yang dipimpinnya.
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
Antarmuka Agen
Pertama-tama kita harus memikirkan informasi apa yang harus dapat dipelajari oleh agen dari lingkungan, dan operasi yang harus dapat dilakukannya. Ini akan mempermudah berpikir tentang algoritma.
Dalam hal ini agen harus dapat menanyakan lingkungan untuk id dari ruangan itu, itu harus bisa mendapatkan hitungan pintu di ruangan itu ( perhatikan ini bukan id dari kamar yang pintu mengarah ke! ) dan dia harus bisa bergerak melalui pintu dengan menentukan indeks pintu. Hal lain yang diketahui agen harus dipecahkan oleh agen itu sendiri.
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
Pengetahuan Agen
Ketika agen pertama kali memasuki peta itu hanya tahu jumlah pintu di ruangan itu, dan id ruangan itu saat ini. Saya perlu membuat struktur yang akan menyimpan informasi yang telah dipelajari agen tersebut seperti pintu mana yang belum melalui, dan di mana pintu mengarah ke yang telah dilaluinya.
Kelas ini mewakili informasi tentang satu kamar. Saya memilih untuk menyimpan pintu yang belum dikunjungi sebagai set
dan pintu yang dikunjungi sebagai dictionary
, di mana kuncinya adalah id pintu dan nilainya adalah id ruangan yang dipimpinnya.
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
Algoritma agen
Setiap kali agen memasuki ruangan, ia mencari kamus pengetahuannya untuk mendapatkan informasi tentang ruangan itu. Jika tidak ada entri untuk ruangan ini maka ia membuat yang baru RoomKnowledge
dan menambahkan ini ke kamus pengetahuannya.
Ia memeriksa untuk melihat apakah ruang saat ini adalah ruang target, jika demikian maka ia kembali.
Jika ada pintu di ruangan ini yang belum kita kunjungi, kita pergi melalui pintu dan menyimpannya. Kami kemudian melanjutkan loop.
Jika tidak ada pintu yang belum dikunjungi, kami menelusuri ruangan yang telah kami kunjungi untuk menemukan satu dengan pintu yang belum dikunjungi.
The Agent
mewarisi kelas dari AgentInterface
kelas.
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)
Fungsi pendukung
Saya harus menulis fungsi yang akan menemukan kunci dalam kamus yang diberi nilai, karena ketika menelusuri kembali kita tahu id ruangan yang sedang kita coba buka, tetapi tidak ke pintu mana yang harus digunakan untuk mendapatkannya.
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
Pengujian
Saya menguji semua kombinasi posisi awal / akhir di peta yang diberikan di atas. Untuk setiap kombinasi, akan dicetak ruang yang dikunjungi.
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))
Catatan
Pelacakan mundur tidak terlalu efisien - dalam skenario kasus terburuk dapat melewati setiap ruangan untuk mencapai ruang yang berdekatan, tetapi penelusuran mundur cukup jarang - dalam tes di atas hanya mundur sebanyak tiga kali. Saya telah menghindari menempatkan penanganan pengecualian agar kode tetap ringkas. Setiap komentar tentang Python saya dihargai :)