Recherche du plus long chemin
Résolu/Fermé
speedzealot
Messages postés
18
Date d'inscription
vendredi 24 juillet 2015
Statut
Membre
Dernière intervention
17 novembre 2015
-
27 août 2015 à 17:52
speedzealot Messages postés 18 Date d'inscription vendredi 24 juillet 2015 Statut Membre Dernière intervention 17 novembre 2015 - 28 août 2015 à 14:11
speedzealot Messages postés 18 Date d'inscription vendredi 24 juillet 2015 Statut Membre Dernière intervention 17 novembre 2015 - 28 août 2015 à 14:11
A voir également:
- Recherche du plus long chemin
- Pc long a demarrer - Guide
- Recherche automatique des chaînes ne fonctionne pas - Guide
- Rechercher ou entrer l'adresse mm - recherche google - Guide
- Recherche adresse - Guide
- Le mot le plus long jeu gratuit - Télécharger - Outils professionnels
1 réponse
KX
Messages postés
16753
Date d'inscription
samedi 31 mai 2008
Statut
Modérateur
Dernière intervention
25 novembre 2024
3 019
Modifié par KX le 27/08/2015 à 19:11
Modifié par KX le 27/08/2015 à 19:11
Bonjour,
"je suis pas sure que ce soit un arbre, mais appelons ca un arbre tout de même vue que son fonctionnement reste le même"
Pour bien commencer, non ce n'est pas un arbre, et non le fonctionnement n'est pas le même. Avec un arbre tu ne peux pas passer d'un noeud "grand-parent" à un noeud "fils" sans passer par le noeud "parent".
Exemple :
Ça c'est un arbre, tu ne peux pas partir de A et aller à C (ou D) sans passer par B.
Ça ce n'est pas un arbre, tu peux partir de A et aller à D en passant par B ou E. Ce qui induis donc que D a "deux parents" (B et E) ce qui est contraire à la définition d'un arbre...
L'avantage d'un arbre c'est qu'il n'y a pas de cycle, ce qui va clairement te poser problème dans ton algorithme ou tu vas tourner en rond...
Ici ton graphe est ce que l'on appelle une grille, d'ailleurs sa représentation aurait pu être simplifiée avec des lignes horizontales et verticales :
Notons au passage que pour relier 90 cases, théoriquement tu ne peux pas avoir plus de 89 arêtes, sinon tu auras forcément des retours en arrière ou des boucles (PS. Je n'ai pas compris ce qu'était un "bloc").
Voici pour info une des solutions optimales de ton problème :
Cette forme "en serpent" est caractéristique, pour maximiser le chemin il faut forcément tourner et tourner encore autour des même noeuds. Donc il est normal que tu n'ais pas une grande diversité dans tes résultats, car plus la solution sera bonne plus elle sera proche d'un serpent et si tu veux une autre forme, ce sera nécessairement au prix d'un chemin moins long.
L'algorithme A* (puisque tu en parles) se base sur une heuristique. Si tu codes ton heuristique de manière à serpenter autour de tes noeuds tu devrais arriver à un chemin relativement long.
Je pose un algo dans ce sens (en reprenant mon exemple plus haut), mais évidement je n'ai aucune idée de ce que ça peut donner en pratique :
Soit X1,Y1 le noeud d'où je viens et X2,Y2 le noeud où je suis (c'est à dire que je viens de tracer l'arête X1Y1-X2Y2) et X3,Y3 le noeud où je veux aller (c'est à dire que l'on va tracer X2Y2-X3Y3 à la prochaine étape)
Remarque : avec une heuristique pareille, même pas besoin de A*, un algorithme glouton pourrait très bien faire l'affaire (ce qui est encore plus rapide à mettre en place et à exécuter).
Par contre il faudra voir comment gérer les cas où la case cible existe déjà, soit en explicitant un second choix pour chaque cas de figure, soit en faisant un peu faire le hasard (ce qui augmentera ta diversité).La confiance n'exclut pas le contrôle
"je suis pas sure que ce soit un arbre, mais appelons ca un arbre tout de même vue que son fonctionnement reste le même"
Pour bien commencer, non ce n'est pas un arbre, et non le fonctionnement n'est pas le même. Avec un arbre tu ne peux pas passer d'un noeud "grand-parent" à un noeud "fils" sans passer par le noeud "parent".
Exemple :
Ça c'est un arbre, tu ne peux pas partir de A et aller à C (ou D) sans passer par B.
A
/
B
/ \
C D
Ça ce n'est pas un arbre, tu peux partir de A et aller à D en passant par B ou E. Ce qui induis donc que D a "deux parents" (B et E) ce qui est contraire à la définition d'un arbre...
A
/ \
B E
/ \ /
C D
L'avantage d'un arbre c'est qu'il n'y a pas de cycle, ce qui va clairement te poser problème dans ton algorithme ou tu vas tourner en rond...
Ici ton graphe est ce que l'on appelle une grille, d'ailleurs sa représentation aurait pu être simplifiée avec des lignes horizontales et verticales :
01---02---03---
| | |
11---12---13---
| | |
21---22---23---
| | |
Notons au passage que pour relier 90 cases, théoriquement tu ne peux pas avoir plus de 89 arêtes, sinon tu auras forcément des retours en arrière ou des boucles (PS. Je n'ai pas compris ce qu'était un "bloc").
Voici pour info une des solutions optimales de ton problème :
01 02---03 04---05 06---07 08---09
| | | | | | | | |
11---12 13---14 15---16 17---18 19
|
21---22 23---24 25---26 27---28 29
| | | | | | | | |
31 32---33 34---35 36---37 38---39
Cette forme "en serpent" est caractéristique, pour maximiser le chemin il faut forcément tourner et tourner encore autour des même noeuds. Donc il est normal que tu n'ais pas une grande diversité dans tes résultats, car plus la solution sera bonne plus elle sera proche d'un serpent et si tu veux une autre forme, ce sera nécessairement au prix d'un chemin moins long.
L'algorithme A* (puisque tu en parles) se base sur une heuristique. Si tu codes ton heuristique de manière à serpenter autour de tes noeuds tu devrais arriver à un chemin relativement long.
Je pose un algo dans ce sens (en reprenant mon exemple plus haut), mais évidement je n'ai aucune idée de ce que ça peut donner en pratique :
Soit X1,Y1 le noeud d'où je viens et X2,Y2 le noeud où je suis (c'est à dire que je viens de tracer l'arête X1Y1-X2Y2) et X3,Y3 le noeud où je veux aller (c'est à dire que l'on va tracer X2Y2-X3Y3 à la prochaine étape)
- Si X2>X1 (on a fait gauche-droite), alors X3=X2, Y3=Y2-1 (bas-haut)
- Si X2<X1 (on a fait droite-gauche), alors X3=X2, Y3=Y2+1 (haut-bas)
- Si Y2>Y1 (on a fait haut-bas), alors X3=X2+1, Y3=Y2 (gauche-droite)
- Si Y2<Y1 (on a fait bas-haut), alors X3=X2-1, Y3=Y2 (droite-gauche)
Remarque : avec une heuristique pareille, même pas besoin de A*, un algorithme glouton pourrait très bien faire l'affaire (ce qui est encore plus rapide à mettre en place et à exécuter).
Par contre il faudra voir comment gérer les cas où la case cible existe déjà, soit en explicitant un second choix pour chaque cas de figure, soit en faisant un peu faire le hasard (ce qui augmentera ta diversité).La confiance n'exclut pas le contrôle
27 août 2015 à 20:56
et merci pour ton explication (je ne connaissait pas le terme de "grille").
Pour le bloc, on va faire un exemple se basant sur l'image que j'ai (c'est en diagonale parce que Mind Mup ne me permet pas de créer des angles droits et je trouve ca plus clair qu'un affichage texte)
Donc, pour ce qui est de ces blocs, je veux dire que le chemin devra etre séparé d'un noeud de toute autre partie de ce même chemin
donc quand je fais : 01 -> 02 -> 12 -> 11, le 11 est adjacent a 01, ce que je ne souhaite pas
un chemin correcte selon cette règle serai plutot 01 -> 02 ->12 -> 22 -> 21. ou la aucun noeud est adjacent a tout autre noeud du chemin (a l'exception du parent évidemment).
(en fait les Noeuds qui m'interessent sont les noeuds qui ne sont pas sur le chemin, et je ne veux pas en avoir trop d'où la recherche des longs chemins)
Après, la solution du serpentin, le gros défaut c'est la diversité, et cela ne donnera pas forcément un long chemin si on déplace le noeud final : si, pour le même graphe on déplace la sortie au noeud 56 c'est mort...
(c'etait la solution que je faisait avant (sur un tableau, pas besoins de graphe pour faire ca), j'y avait rajouté des paramètres aléatoire par rapport au changement de direction, mais j'ai tout effacé pour trouvé un truc plus optimal)
Ca voudrai dire que l'heuristique d'A* serai en fonction de la taille du graphe (oui, le serpentin ne marche pas bien pour des dimensions impaires), et en fonction de l'emplacement de la sorte en fonction de sa position relative par rapport a la forme de la grille, enfin le tout donnerai une trop grosse surcharge de calculs.. (après j'ai peut-etre tord, je n'en sait rien ^^)
ah et non, l'absense de diversité viens du fait que je fais un parcours en profondeur, pas de la forme serpentin (oui, il y a Beaucoup de manière pour obtenir un chemin de taille Dim/2, et les solutions optimales il y en a une petite dizaine (j'ai pas vraiment compté, c'est chiant de se ballader dans un fichier txt de 54000 ligne :D) qui ont a peu près la même taille, donc pas que des serpentins ^^)
Pour parcours en profondeur, admettons qu'il ai trouvé un chemin de taille 50 en terminant par 97 -> 98 -> 99, la récursion va remonter jusqu'a 97 (a cause de la règle du bloc), puis le prochain sur la liste terminera par 97 -> 87 -> 88 -> 89 -> 99, donc tout le chemin parcouru jusqu'a 97 sera identique pour ces deux chemins trouvés
27 août 2015 à 23:23
Si j'ai bien compris, tu veux :
Déjà à mon avis il faut oublier A* ton problème ne s'y prête pas (recherche de maximum et pas du minimum, nombre de contraintes importantes, etc.), il va plutôt falloir sortir l'artillerie lourde et s'orienter vers les métaheuristiques.
Modifié par speedzealot le 28/08/2015 à 09:55
(j'aurai peut-etre du commencer par l'image pour etre plus clair, dsl)
l'entrée est en haut a gauche, la sortie en bas a droite, les 0 représentent le chemin généré par l'algo, les autres chiffres sont les noeuds qui m'interesse et je ne veux pas en avoir beaucoup. (donc Dim*0.8/1.8 "murs" me vas tres bien)
au niveau de la diversitée, si un chemin (de 0) ressemble à plus de 66% (ce chiffre n'est pas définitif) à un autre chemin, il sera effacé.
Merci pour m'avoir orienté vers les métaheuristiques (je ne connaissait pas) mais ca a l'aire d'etre exactement ce que je recherche :)
je vais faire des recherches la dessus
28 août 2015 à 11:56
Modifié par KX le 28/08/2015 à 13:56
Pseudo-code :
Remarque : ça c'est l'algorithme générique du recuit, maintenant il faut l'adapter à ton problème, c'est à dire :
1) Déterminer la solution de départ, . Elle peut être quelconque (exemple: le chemin le plus court entre l'entrée et la sortie), mais si elle n'est pas trop mauvaise dès le départ (obtenu par une heuristique) ça donnera de meilleurs résultats plus rapidement... Sauf que du coup tu orienteras la recherche et donc tu vas perdre en diversité.
À voir ce que tu veux le plus : diversité vs rapidité.
2) Calculer une solution voisine
Quand on parle de solution voisine, ça veut dire que les deux chemins obtenus doivent se ressembler à "un" changement près. Il ne faut pas que les solutions soient trop différentes l'une de l'autre. Remarque : les voisins sont aléatoirement choisis (et il faut que ce soit rapide vu que c'est l'opération que l'on va faire à chaque tour de boucle).
Par exemple, tu peux couper ton chemin en supprimant une cellule (case bleu sur mon illustration) et tu "recolles" les deux morceaux par une "déviation" (orange) la plus courte possible.
Attention : une solution doit toujours être valide, on ne doit jamais obtenir de chemin qui serait faux (par exemple avec des blocs), si en calculant un voisin tu te retrouves avec une solution invalide, il faudra trouver un autre voisin valide.
Il est par exemple envisageable qu'en voulant supprimer une case (bleue), tu doives faire le ménage et supprimer plus de cases (violette) pour que ta déviation (orange) soit un chemin acceptable.
Le choix des voisins est primordial dans les métaheuristiques, je t'invite à tester plusieurs fonctions de création de voisins pour voir s'il n'y en a pas une qui fonctionne mieux que les autres.
NB. il y a également du paramétrage à faire, en particulier sur la température, à voir ce que ça te donne quand tu exécutes le programme.