Eu reconheço que você provavelmente entendeu a essência de outras respostas, mas foi uma pergunta divertida e tive vontade de escrever um pouco de código Python. Esta é a minha abordagem orientada a objetos. Recuo define o escopo.
Representação gráfica
O gráfico pode ser facilmente armazenado como uma chave, dicionário de valores em que a chave é o ID da sala e o valor é uma matriz das salas às quais ele leva.
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
Interface do agente
Primeiro, devemos pensar sobre quais informações o agente deve ser capaz de aprender com o ambiente e as operações que ele deve ser capaz de executar. Isso simplificará o pensamento sobre o algoritmo.
Nesse caso, o agente deve ser capaz de consultar o ambiente para identificar o ID da sala em que está, deve conseguir obter uma contagem das portas na sala em que está ( observe que esse não é o ID dos quartos nos quais o portas levam a! ) e ele deve poder passar por uma porta especificando um índice de porta. Qualquer outra coisa que um agente saiba precisa ser descoberta pelo próprio agente.
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
Conhecimento do agente
Quando o agente entra no mapa pela primeira vez, ele sabe apenas a quantidade de portas na sala e a identificação da sala em que está atualmente. Eu precisava criar uma estrutura que armazenasse informações que o agente havia aprendido, como quais portas não haviam sido fechadas. através de, e onde as portas levam a que é passou.
Esta classe representa as informações sobre um quarto individual. Eu escolhi armazenar as portas não visitadas como a set
e as portas visitadas como a dictionary
, onde a chave é o ID da porta e o valor é o ID da sala que ele leva.
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
Algoritmo do agente
Cada vez que o agente entra em uma sala, ele procura informações no seu dicionário de conhecimento. Se não houver entradas para esta sala, ela cria uma nova RoomKnowledge
e a adiciona ao seu dicionário de conhecimento.
Ele verifica se a sala atual é a sala de destino e, se sim, retorna.
Se houver portas nesta sala que não visitamos, passamos pela porta e armazenamos para onde ela leva. Continuamos o ciclo.
Se não havia portas não visitadas, voltamos atrás pelas salas que visitamos para encontrar uma com portas não visitadas.
A Agent
classe herda da AgentInterface
classe.
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)
Funções de suporte
Eu tive que escrever uma função que encontrasse uma chave em um dicionário, devido a um valor, pois ao retornar, sabemos o ID da sala em que estamos tentando chegar, mas não qual porta usar para acessá-la.
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
Teste
Testei todas as combinações de posição inicial / final no mapa fornecido acima. Para cada combinação, imprime os quartos visitados.
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))
Notas
O retorno não é muito eficiente - na pior das hipóteses, poderia passar por todos os cômodos para chegar a um cômodo adjacente, mas o retorno é bastante raro - nos testes acima, ele retrocede apenas três vezes. Evitei colocar manipulação de exceção para manter o código conciso. Quaisquer comentários no meu Python apreciado :)