J'ai besoin d'écrire un programme qui résoudra le labyrinthe. Maze a une structure graphique, où chaque nœud - une pièce et des bords - sort vers d'autres pièces:
Spécification:
- Nous partons d'une pièce au hasard.
- Maze a des impasses, 0 ou quelques sorties.
- Nous ne savons rien de tout le labyrinthe, seulement le nombre de pièces actuelles et la liste des portes.
- Lorsque nous entrons dans une nouvelle pièce, nous ne savons pas d'où nous venons (quelle porte de la pièce actuelle nous ramène à la pièce précédente).
- Nous pouvons reconnaître quand nous atteignons la sortie.
- À chaque étape, nous passons de la pièce actuelle à une porte disponible.
- Si nous sommes à la salle 6 par exemple, nous ne pouvons pas simplement sauter pour commencer. C'est comme un mouvement de robot.
- Nous savons exactement l'ID de la pièce actuelle. Nous connaissons l'ID de chaque porte de la pièce actuelle (pas dans tous les labyrinthes).
- Nous contrôlons le robot.
J'ai regardé tous les algorithmes connus, mais ils nécessitent tous au moins une capacité supplémentaire pour revenir à la pièce précédente. Selon les spécifications, nous ne pouvons utiliser aucun algorithme qui recherche le chemin le plus court (en fait, je n'ai pas besoin du plus court), car nous ne connaissons que la salle actuelle. Nous ne pouvons pas utiliser les algorithmes suivants à gauche (droite), car nous ne connaissons pas la direction des sorties. Probablement, la seule solution qui répond aux spécifications est de choisir une sortie aléatoire dans chaque pièce en espérant qu'une sortie de temps sera trouvée ...
Une suggestion sur la façon de résoudre un tel labyrinthe de manière plus intelligente?
Réponses:
Hmm, vous connaissez le numéro de la pièce réelle. Vous pouvez donc créer une structure de données. Je suppose que la liste des sorties n'a pas de numéro de chambre. Mais après en avoir choisi un au hasard, vous savez au moins qu'il existe une connexion.
Dites que vous êtes dans la salle 4 et choisissez l'une des trois sorties aléatoires. Le système vous indique maintenant que vous êtes dans la salle 6 et qu'il ne vous reste qu'une seule sortie. Vous choisissez cela et vous êtes de retour dans la salle 4. À ce stade, vous avez rassemblé des informations sur la structure du labyrinthe. Vous choisissez maintenant une autre sortie et vous terminez dans la salle 5. Informations Moe sur la salle 4 (une sortie vers 6, une sortie vers 5)
Pouvez-vous choisir une sortie spécifique? sont-ils numérotés, disons que si dans la salle 4 vous choisissez la sortie une, vous finissez toujours par 6? Sinon, vous pouvez au moins vous renseigner sur les itinéraires possibles.
Ok, lisez simplement votre commentaire. Donc, si les sorties ont des identifiants et que ceux-ci sont liés statiquement à une pièce (même si vous ne savez pas laquelle pour commencer), vous en choisissez simplement une nouvelle et vous souvenez des connexions sortie / chambre et rappelez-vous quelle sortie a déjà été essayée. Essayez des sorties non essayées jusqu'à ce que vous ayez fouillé chaque pièce.
De cette façon, c'est en fait simple. Après quelques étapes, vous devriez avoir une liste plus ou moins complète de connexions. Ce n'est que lorsque vous entrez dans une nouvelle pièce que vous pouvez (pour quelques étapes) courir au hasard. Mais à chaque étape, vous obtenez plus d'informations et chaque fois que vous entrez dans une pièce visitée auparavant, vous pouvez prendre une décision plus intelligente (ne pas tester à nouveau la salle sans issue 6 par exemple lorsque vous retrouvez à 4, car il n'y a pas de sorties non testées).
Modifier L'idée est de faire des étapes aléatoires en premier et de consigner les informations que vous trouvez comme je l'ai décrit (la description de Dan est plus concise). Si vous vous trouvez dans une pièce sans sortie inconnue, vous pouvez utiliser n'importe quel éclaireur connu pour trouver le chemin le plus court vers une pièce qui a des sorties que vous n'avez pas encore explorées.
Pas sûr à 100%, mais je pense que Peter Norvig a écrit sur un problème similaire (le labyrinthe de Wumpus) dans son livre "Intelligence artificielle: une approche moderne". Mais si je me souviens bien, il s'agissait moins de trouver un chemin et plus de prendre des décisions concernant certaines informations que le système pourrait obtenir sur les pièces voisines.
Éditer:
Non, ce n'est pas seulement aléatoire. En gardant une trace des sorties déjà essayées, vous supprimez la redondance inutile. En fait, vous n'avez même pas besoin de choisir au hasard.
Supposons que vous commenciez dans la salle 4. Info que vous obtenez: 3 sorties A, B, C Vous choisissez toujours la première sortie maintenant inutilisée. Commencez donc par A. Vous terminez dans la salle 6. Maintenant, vous vous souvenez de 4A => 6 (et utilisé) dans la salle 6, vous obtenez l'info 1 sortie A. Encore une fois, vous choisissez la première sortie inutilisée (et dans ce cas uniquement la sortie) Retour dans la salle pour connaître 6A => 4 (et aucune autre sortie dans la salle 6) Maintenant, vous choisissez la prochaine sortie B et atteignez la salle 5 ...
Tôt ou tard, vous aurez fouillé toutes les pièces de cette façon. Mais de manière systématique.
La seule raison pour laquelle vous auriez besoin d'une recherche de chemin est lorsque vous vous trouvez dans une pièce où toutes les sorties sont déjà explorées. Ensuite, vous voudrez trouver un chemin direct vers la pièce suivante avec des sorties inexplorées pour aller de l'avant avec votre recherche. Donc, l'astuce principale est moins de savoir quelle sortie mène à quelle pièce (bien que cela puisse être utile) mais de garder une trace des sorties non encore essayées.
De cette façon, par exemple, vous pouvez éviter de tourner en rond tout le temps, ce qui serait un risque pour une approche purement aléatoire.
Dans votre exemple de labyrinthe, cela n'aurait probablement pas beaucoup d'importance. Mais dans un grand labyrinthe avec de nombreuses pièces et connexions et peut-être des pièces disposées de façon circulaire et délicate, ce système garantit que vous trouverez la sortie avec le moins d'essais possible.
(Je pense que c'est probablement le même système que Byte56 avec Gamers)
la source
Je reconnais que vous avez probablement compris l'essentiel des autres réponses, mais c'était une question amusante et j'avais envie de faire un peu de codage Python. Ceci est mon approche orientée objet. L'indentation définit la portée.
Représentation graphique
Le graphique peut facilement être stocké sous forme de clé, dictionnaire de valeurs où la clé est l'identifiant de la pièce et la valeur est un tableau des pièces vers lesquelles elle mène.
Interface de l'agent
Nous devons d'abord réfléchir aux informations que l'agent devrait être en mesure d'apprendre de l'environnement et aux opérations qu'il devrait être en mesure d'effectuer. Cela simplifiera la réflexion sur l'algorithme.
Dans ce cas, l'agent devrait pouvoir interroger l'environnement pour l'identifiant de la pièce dans laquelle il se trouve, il devrait être en mesure d'obtenir un compte des portes de la pièce dans laquelle il se trouve ( notez qu'il ne s'agit pas de l'identifiant des pièces dans lesquelles il se trouve). portes mènent à! ) et il doit pouvoir se déplacer à travers une porte en spécifiant un index de porte. Tout ce qu'un agent sait doit être déterminé par l'agent lui-même.
Connaissance des agents
Lorsque l'agent entre pour la première fois sur la carte, il ne connaît que le nombre de portes dans la pièce et l'identifiant de la pièce dans laquelle il se trouve actuellement. à travers, et où les portes mènent à cela était passé.
Cette classe représente les informations sur une seule pièce. J'ai choisi de stocker les portes non visitées comme un
set
et les portes visitées comme undictionary
, où la clé est l'identifiant de la porte et la valeur est l'identifiant de la pièce vers laquelle elle mène.Algorithme d'agent
Chaque fois que l'agent pénètre dans une pièce, il recherche dans son dictionnaire de connaissances des informations sur la pièce. S'il n'y a pas d'entrées pour cette salle, il en crée une nouvelle
RoomKnowledge
et l'ajoute à son dictionnaire de connaissances.Il vérifie si la pièce actuelle est la pièce cible, si c'est le cas, il revient.
S'il y a des portes dans cette pièce que nous n'avons pas visitées, nous passons par la porte et stockons où elles mènent. Nous continuons ensuite la boucle.
S'il n'y avait pas de portes non visitées, nous revenons en arrière dans les pièces que nous avons visitées pour en trouver une avec des portes non visitées.
La
Agent
classe hérite de laAgentInterface
classe.Fonctions de support
J'ai dû écrire une fonction qui trouverait une clé dans un dictionnaire étant donné une valeur, car lors du retour en arrière, nous connaissons l'identifiant de la pièce que nous essayons d'accéder, mais pas la porte à utiliser pour y accéder.
Essai
J'ai testé toutes les combinaisons de position de début / fin dans la carte ci-dessus. Pour chaque combinaison, il imprime les pièces visitées.
Remarques
Le retour arrière n'est pas très efficace - dans le pire des cas, il pourrait traverser chaque pièce pour se rendre dans une pièce adjacente, mais le retour arrière est assez rare - dans les tests ci-dessus, il ne fait que revenir en arrière trois fois. J'ai évité de mettre la gestion des exceptions pour garder le code concis. Tout commentaire sur mon Python apprécié :)
la source
Essentiellement, vous avez un graphique directionnel, où chaque pièce connectée est reliée par deux passages inconnus - un dans l'une ou l'autre direction. Disons que vous commencez dans le nœud
1
, les portesA
etB
sortez. Vous ne savez pas ce qui se cache au-delà de chaque porte, vous choisissez donc simplement la porteA
. Vous obtenez à la chambre2
, qui a des portesC
,D
etE
. Vous savez maintenant que la porteA
mène de pièce1
en pièce2
, mais vous ne savez pas comment revenir, vous choisissez donc la porte au hasardC
. Vous rentrez dans la chambre1
! Vous savez maintenant comment vous déplacer entre les chambres1
et2
. Continuez à explorer par la porte inconnue la plus proche jusqu'à ce que vous trouviez la sortie!la source
Étant donné que les chambres sont toujours dans le même ordre dans les listes de sorties, nous pouvons faire un plan rapide des chambres tout en recherchant une sortie.
Mon pseudo code est un peu Javaish, désolé, je l'utilise beaucoup ces derniers temps.
Unvisited_Rooms est une table de hachage contenant un ID de salle et une liste d'index des salles non mappées Ou un tableau 2D, tout ce qui fonctionne.
J'imagine que l'algorithme pourrait ressembler à ceci:
Vous devrez utiliser l'un des moteurs de recherche de chemin de nœud communs aux salles PathTo () dans "la carte". J'espère que c'est assez clair pour vous aider à démarrer.
la source
Je ne suis pas trop clair sur vos besoins, mais si ce qui suit est autorisé, il peut s'agir d'un algorithme simple à suivre. Probablement un bogue là-dedans, d'autant plus qu'il utilise une fonction récursive. De plus, il vérifie si une porte mène à la pièce d'où vous venez, mais je ne sais pas comment un chemin circulaire à trois pièces pourrait gérer, il peut simplement continuer à boucler pour toujours dans ces trois pièces. Vous devrez peut-être ajouter un historique pour vous assurer qu'aucune chambre n'est vérifiée deux fois. Mais en lisant votre description, cela peut ne pas être autorisé.
[Modifier] Ajouté 'id' à la vérification précédente et mis à jour pour rendre plus orienté objet.
la source
curRoom.doors <= 1
, donc la fonction revient immédiatement, sachant qu'elle est dans une impasse, mais pensant qu'elle a déjà exploré l'intégralité du labyrinthe.La réponse courte est une recherche en profondeur avec retour en arrière. Vous pouvez faire de l'ampleur en premier si vous préférez, mais votre petit robot fera alors beaucoup plus de va-et-vient.
Plus concrètement, supposons qu'on nous donne:
Pour trouver la sortie, nous avons juste besoin de:
Appelez
escape()
avec l'ID de la salle de départ et il déplacera le robot vers la sortie (en appelantmoveTo()
).la source
escape(int startingRoom)
devrait appelerescape(Stack<int> path)
if (path.contains(door)) continue;
viole ses exigences - l'agent ne sait pas vraiment si une porte mène à une pièce dans laquelle il a déjà été à moins qu'il ne franchisse la porte.