Reconozco que probablemente obtuviste la esencia de otras respuestas, pero fue una pregunta divertida y tuve ganas de hacer una pequeña codificación de Python. Este es mi enfoque orientado a objetos. La sangría define el alcance.
Representación Gráfica
El gráfico se puede almacenar fácilmente como una clave, un diccionario de valores donde la clave es la identificación de la sala, y el valor es una matriz de las salas a las que conduce.
map = {
1:[5, 2],
2:[1, 3, 5],
3:[2, 4],
4:[3, 5, 6],
5:[2, 4, 1],
6:[4]
}
Interfaz de agente
Primero debemos pensar qué información debería poder aprender el agente del entorno y las operaciones que debería poder realizar. Esto simplificará el pensamiento sobre el algoritmo.
En este caso, el agente debería poder consultar en el entorno la identificación de la habitación en la que se encuentra, debería poder contar las puertas de la habitación en la que se encuentra ( tenga en cuenta que esta no es la identificación de las habitaciones las puertas conducen a! ) y debería poder moverse a través de una puerta especificando un índice de puerta. Cualquier otra cosa que un agente sepa tiene que ser resuelta por el propio 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
Conocimiento del agente
Cuando el agente ingresa por primera vez al mapa, solo conoce la cantidad de puertas en la habitación y la identificación de la habitación en la que se encuentra actualmente. Necesitaba crear una estructura que almacenara la información que el agente había aprendido, como qué puertas no había sido a través, y por donde habían pasado las puertas.
Esta clase representa la información sobre una habitación individual. Elegí almacenar las puertas no visitadas como a set
y las puertas visitadas como a dictionary
, donde la clave es la identificación de la puerta y el valor es la identificación de la habitación a la que conduce.
class RoomKnowledge(object):
def __init__(self, unvisited_door_count):
self.unvisited_doors = set(range(unvisited_door_count))
self.visited_doors = {}
Algoritmo de agente
Cada vez que el agente ingresa a una sala, busca en su diccionario de conocimiento información sobre la sala. Si no hay entradas para esta sala, crea una nueva RoomKnowledge
y agrega esto a su diccionario de conocimiento.
Comprueba si la habitación actual es la habitación objetivo, si es así, vuelve.
Si hay puertas en esta sala que no hemos visitado, atravesamos la puerta y almacenamos a donde conduce. Luego continuamos el ciclo.
Si no había puertas sin visitar, retrocedemos por las habitaciones que hemos visitado para encontrar una con puertas sin visitar.
La Agent
clase hereda de la AgentInterface
clase.
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)
Funciones de apoyo
Tuve que escribir una función que encontrara una clave en un diccionario dado un valor, ya que cuando retrocedemos sabemos la identificación de la habitación a la que estamos tratando de llegar, pero no qué puerta usar para llegar a ella.
def find_key(dictionary, value):
for key in dictionary:
if dictionary[key]==value:
return key
Pruebas
Probé todas las combinaciones de posición de inicio / fin en el mapa dado anteriormente. Para cada combinación imprime las habitaciones visitadas.
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
El retroceso no es muy eficiente: en el peor de los casos, podría atravesar cada habitación para llegar a una habitación adyacente, pero el retroceso es bastante raro: en las pruebas anteriores solo retrocede tres veces. He evitado poner el manejo de excepciones para mantener el código conciso. Cualquier comentario sobre mi Python apreciado :)