Forum |  HardWare.fr | News | Articles | PC | S'identifier | S'inscrire | Shop Recherche
1067 connectés 

  FORUM HardWare.fr
  Programmation
  Algo

  Graphe Orienté : existence chemin longueur k ?

 


 Mot :   Pseudo :  
 
Bas de page
Auteur Sujet :

Graphe Orienté : existence chemin longueur k ?

n°1260106
bugmenot
Posté le 06-12-2005 à 15:05:10  profilanswer
 

Salut,
 
Voilà je travaille sur les graphes orientés, plus précisemment sur des graphes ayant des arcs valués par des symboles. Mon graphe représente donc un automate. Chaque arc qui relie 2 sommets, a pour longueur 1.
 
Je cherche donc un algo qui permet de trouver s'il existe un chemin de longueur k (donné) entre l'état initial ( le sommet source du graphe ) et un état final de l'automate ( un sommet quelconque ). Autrement dit si l'automate permet de générer des mots de longueur k.
Le graphe représentant l'automate peut comporter un ou plusieurs cycles, ou pas du tout.
 
Connaissez vous un algo qui permet de résoudre ce problème ? Ou avez vous une idée ?
Si possible un algo qui repose sur la recherche en profondeur à partir du sommet initial.
 
Merci d'avance et @ bientot !

mood
Publicité
Posté le 06-12-2005 à 15:05:10  profilanswer
 

n°1260198
Profil sup​primé
Posté le 06-12-2005 à 16:01:09  answer
 

Ben tu donnes la réponse toi-même, non ? Tu fais une recherche en profondeur toute simple. Style :
 


FONCTION rechercher(k, i, etat_courant)
  SI i == k ALORS
    RENVOYER est_terminal(etat_courant)
  FINSI
 
  POUR CHAQUE etat_suivant = cible_suivante(etat_courant)
    SI rechercher(k, i+1, etat_suivant) ALORS
      RENVOYER VRAI
    FINSI
  FINPOUR
 
  RENVOYER FAUX
FINFONCTION


 
Ca revient en gros à regarder si un mot donné de longueur k sur un alphabet à une lettre unique est reconnu par l'automate non déterministe correspondant à ton graphe où toutes les lettres se confondent en une.


Message édité par Profil supprimé le 06-12-2005 à 16:02:54
n°1260221
bugmenot
Posté le 06-12-2005 à 16:21:30  profilanswer
 

Le problème c'est que si le graphe comporte un circuit ou un arc reflexif ( un sommet pointe sur lui meme ), l'algo va tourner en rond.
 
Le problème est que cet algo ( je pense ) n'effectue pas toutes les possibilitées. Si au bout de k étapes, on est pas sur un état final, il faut revenir en arrière pour visiter le successeur suivant de l'état précédent ( s'il existe ).

n°1260246
Profil sup​primé
Posté le 06-12-2005 à 16:42:31  answer
 

Mon programme ne boucle pas indéfiniment puisqu'il atteint une profondeur de k. De plus tous les chemins possibles sont explorés, c'est le principe du parcours en profondeur. :)
 
Il faut "penser récursivement" : ma boucle explore tous les successeurs de "etat_courant" (si on renvoie VRAI à un moment, c'est fini), donc elle explore tous les chemins possibles de longueur k à partir de l'état initial si besoin.


Message édité par Profil supprimé le 06-12-2005 à 16:45:57
n°1260249
flo850
moi je
Posté le 06-12-2005 à 16:45:25  profilanswer
 

d'ou l'importance de borner la taille du mot a rechercher  
tu ne peux pas , avec ce type d'algo retrouver des mot de type ab*


---------------

n°1260263
bugmenot
Posté le 06-12-2005 à 16:55:02  profilanswer
 

flo850 pour l'instant je ne cherche pas a trouver si un mot ab* ou abba* peut etre généré par l'automate représenter par le graphe.
 
Je cherche juste à savoir s'il peut générer des mots de longueur k.
 
( Quand j'aurai fini ce probleme, il me faudra savoir, si l'automate peut générer des mots ayant pour facteur une sous suite de symbole donnée. Par exemple on me donne la suite abba, je dois savoir si un mot du style b'abba'bba peut etre engendré par l'automate )

n°1260271
Profil sup​primé
Posté le 06-12-2005 à 17:00:01  answer
 

Ben l'algo je te l'ai donné, je vois pas ce qu'il te faut de plus... Tu peux l'optimiser en évitant de boucler k-i fois sur le même état s'il est terminal, mais le principe du parcours en pronfondeur c'est ça, et mon algo fonctionne très bien. :)

n°1260281
bugmenot
Posté le 06-12-2005 à 17:06:18  profilanswer
 

J'ai codé ton algo :
 

Code :
  1. /* nombre de sommet maximum */
  2. #define n_max 25
  3. typedef struct arc {
  4. char * arete; /* valeur de l'arete */
  5. int som; /* indice du sommet pointe */
  6. struct arc * suiv; /* arc suivant */
  7. } Arc;
  8. typedef Arc * listeArc;
  9. typedef struct sommet {
  10. int som; /* numero du sommet de 0 a n_max, -1 si inexistant */
  11. int etat; /* 0 -> initial, 1 -> final, 2 -> initial + final, -1 sinon */
  12. listeArc succ; /* successeurs du sommet */
  13. } Sommet;
  14. typedef struct {
  15. Sommet s[n_max]; /* tableau des sommets */
  16. int n; /* nombre de sommets au départs */
  17. int nb_som; /* nombre de sommets courants */
  18. } graphe;


 

Code :
  1. int longueur_mot(graphe g, int longueur)
  2. /* specif : retourne 1 s'il existe des mots d'une certaine longueur donnee,   */
  3. /*          0 sinon ( O() )                                                   */
  4.    int i, initial;
  5.    /* recherche de l'etat initial */
  6.    for(i = 0; i < g.n; i++)
  7.       if(g.s[i].etat == 0) initial = i;
  8.  
  9.    return longueur_rec(g, initial, longueur, 0);
  10. }


 

Code :
  1. int longueur_rec(graphe g, int x, int k, int cpt)
  2. /* specif : retourne 1 s'il existe un mot de longueur k, 0 sinon              */
  3. /*          ( O() )                                                           */
  4. {
  5.    listeArc temp = g.s[x].succ;
  6.  
  7.    if((cpt == k) && ((g.s[x].etat == 1) || (g.s[x].etat == 2)))
  8.       return 1;
  9.    while(temp != NULL)
  10.    {
  11.       if(longueur_rec(g, temp->som, k, cpt + 1) == 1)
  12.          return 1;
  13.       temp = temp->suiv;
  14.    }
  15.    return 0;
  16. }


 
Mais ca ne marche pas :/

n°1260298
bugmenot
Posté le 06-12-2005 à 17:16:24  profilanswer
 

Dans le cas où le graphe se résume a un seul sommet qui posséede un arc reflexif, ca coince déjà ^^
 
Car il va aller sur le successeur ( donc lui meme ), il va relancer la fonction, ca va aller sur le successeur ( lui meme encore ), et il va encore relancer, et ainsi de suite ...

n°1260308
Profil sup​primé
Posté le 06-12-2005 à 17:21:21  answer
 

Si cpt == k, il faut s'arrêter que l'état courant soit terminal ou non ! Là en effet tu as une jolie récursion infinie.
 
Je te conseille aussi de créer des "boîtes noires" du style "est_terminal()", "est_initial()"... enfin bref, faire de la programmation objet, ça me paraît être adapté à la situation.

mood
Publicité
Posté le 06-12-2005 à 17:21:21  profilanswer
 

n°1260311
Profil sup​primé
Posté le 06-12-2005 à 17:23:15  answer
 

bugmenot a écrit :

Dans le cas où le graphe se résume a un seul sommet qui posséede un arc reflexif, ca coince déjà ^^
 
Car il va aller sur le successeur ( donc lui meme ), il va relancer la fonction, ca va aller sur le successeur ( lui meme encore ), et il va encore relancer, et ainsi de suite ...


 


  SI i == k ALORS  
    RENVOYER est_terminal(etat_courant)  
  FINSI  


 
c'est différent de :
 


  SI i == k ET est_terminal(etat_courant) ALORS  
    RENVOYER TRUE
  FINSI

n°1260322
bugmenot
Posté le 06-12-2005 à 17:32:35  profilanswer
 

Si cpt = k, il ne faut pas s'arreter forcément.
 
En effet, si on part de l'état initial qui ne possede dans ces successeurs qu'un sommet x, lequel x possede un arc reflexif ( et d'autres successeurs ), lorsqu'on va arriver sur x, on va revenir sur x, puis encore sur x, jusqu'a avoir cpt = k. Donc selon toi il faut s'arreter et conclure que le graphe n'engendre pas de mot de longueur k. Hors on n'aura pas visité la descendance complete de x.
 
Du coup pour résoudre le probleme, cela devient plus compliqué, et je n'y arrive pas :@

n°1260339
Profil sup​primé
Posté le 06-12-2005 à 17:50:57  answer
 

Tu parlais d'automate dans ton premier post... Pour moi "engendrer" un mot de longueur k voulait dire "l'automate fini correspondant au graphe reconnaît le mot de longueur k". Dans ton exemple, après k itérations, si l'état sur lequel on a bouclé est terminal, alors le mot est reconnu, sinon le mot n'est pas reconnu. [:spamafote]

n°1260348
bugmenot
Posté le 06-12-2005 à 17:58:59  profilanswer
 

Un mot de longueur k est un mot quelconque possédant k symboles.
 
Si l'état sur lequel on a bouclé n'étais pas terminal, alors il faut quand meme exploré le reste du graphe ( qui dans mon cas représente bien un automate non déterministe )

n°1260363
Profil sup​primé
Posté le 06-12-2005 à 18:11:10  answer
 

bugmenot a écrit :

Un mot de longueur k est un mot quelconque possédant k symboles.
 
Si l'état sur lequel on a bouclé n'étais pas terminal, alors il faut quand meme exploré le reste du graphe ( qui dans mon cas représente bien un automate non déterministe )


 
Si ton graphe ne comporte qu'un sommet qui boucle sur lui même je ne vois pas ce qu'il reste à explorer... S'il comporte d'autres sommets, ils seront explorés puisque qu'à partir de chaque sommet on explore tous ses voisins et donc au final tous les états accessibles (en au plus k transitions évidemment !) puisqu'on part de l'état initial.
 
Ça me paraît quand même pas difficile à comprendre... Il faut voir que l'algorithme que j'ai décrit plus haut réalise un backtracking, c'est à dire qu'il teste si en partant du premier voisin du sommet courant, le résiduel de longueur k-1 est reconnu, sinon il regarde en partant du deuxième voisin, et ainsi de suite jusqu'à ce qu'il en trouve un à partir duquel on atteint un état terminal au bout de k-i itérations (s'il n'en trouve pas la boucle se termine et la fonction renvoie FAUX).


Message édité par Profil supprimé le 06-12-2005 à 18:27:18
n°1260480
bugmenot
Posté le 06-12-2005 à 19:20:51  profilanswer
 

MERCIIIII A TOI alerim ! ! !
 
Tu m'as ouvert les yeux :p
 
Il me manquait juste un test dans mon code ( oublie ), du coup l'algo ne fonctionnait pas ^^
 
En effet j'ai rajouté à ton algo :
 

Code :
  1. FONCTION rechercher(k, i, etat_courant)
  2.   SI i == k ALORS
  3.     RENVOYER est_terminal(etat_courant)
  4.   FINSI
  5.   SI i > k ALORS
  6.     RENVOYER FAUX
  7.   FINSI
  8.   POUR CHAQUE etat_suivant = cible_suivante(etat_courant)
  9.     SI rechercher(k, i+1, etat_suivant) ALORS
  10.       RENVOYER VRAI
  11.     FINSI
  12.   FINPOUR
  13.   RENVOYER FAUX
  14. FINFONCTION


 
Le test si on avait depassé k.
 
VOILA en tout cas un grand merci à toi, tu as eu du courage avec moi ^^
 
Allé merci encore et @ bientot peut etre ;)

n°1260488
Profil sup​primé
Posté le 06-12-2005 à 19:36:50  answer
 

Hum, je suis pas sûr que tu aies tout saisi si tu penses qu'il est utile de tester i > k. C'est inutile puisque pour appeler rechercher avec la valeur k+1 pour le paramètre i, il faudrait avoir passé "SI i == k ALORS" avec i == k. Or dans ce cas, on quitte la fonction donc ça n'est pas possible d'atteindre une valeur strictement supérieure à k pour i.
 
En revanche dans ton implémentation du dessus, tu ne fais pas que tester "i == k", tu testes également si l'état courant est terminal. Finalement tu as dû écrire quelque chose du style :
 


   if((cpt == k) && ((g.s[x].etat == 1) || (g.s[x].etat == 2)))  
      return 1;
 
   if (cpt > k)
      return 0;


 
qui est équivalent à :
 


   if(cpt == k) /* ou cpt >= k, mais j'aime bien être averti quand un rayon
                     cosmique modifie le déroulement de mon programme. :D */
      return (g.s[x].etat == 1) || (g.s[x].etat == 2);


 
qui fait l'économie d'un niveau de récursion.


Message édité par Profil supprimé le 06-12-2005 à 19:39:38
n°1260497
bugmenot
Posté le 06-12-2005 à 19:49:37  profilanswer
 

Si on ne met pas le test cpt > k, cela ne marche plus.
 
En effet, pour TOUT cpt != k, on ne retournera rien avec ton premier test. Donc on arriverai directement sur la boucle while et là, la boucle peut etre infinie à cause des cycles ou arcs reflexifs ...

n°1260530
bugmenot
Posté le 06-12-2005 à 20:44:36  profilanswer
 

Pour la complexité par contre, t'as une idée ?
 
Je pense que c'est du O(n + m) mais le parametre k a son importance quand meme
 
n = nombre de sommet
m = nombre d'arc

n°1260540
Profil sup​primé
Posté le 06-12-2005 à 21:01:07  answer
 

bugmenot a écrit :

Donc on arriverai directement sur la boucle while et là, la boucle peut etre infinie à cause des cycles ou arcs reflexifs ...


 
Non, combien de fois faut-il le répéter... Quand cpt vaudra k, la récursion (ce que tu appelles la boucle) se terminera sauf si tu fais le test que tu as ajouté dans le if (savoir si l'état courant est terminal ou pas) et qui n'est pas au même endroit dans mon algo. Je le répète une dernière fois : mon algo est correct et ne boucle PAS indéfiniment et ta version est inutilement compliquée. :o
 
Edit: Hum j'ai lu un peu trop vite, tu parles de la boucle "while" qui pourrait être infinie ? Si ça se produit c'est un problème d'implémentation. Tu dois  récupérer la liste des sommets qui peuvent être atteints à partir du sommet courant. Cette liste est finie et tu la parcours séquentiellement, donc ta boucle while ne devrait pas pouvoir être infinie en aucun cas. Et de toutes façons dans ce cas le test cpt > k n'a absolument rien à voir avec ce problème. :D
 
Ah puis aussi :
 

Citation :

En effet, pour TOUT cpt != k, on ne retournera rien avec ton premier test.


 
Ben si cpt != k, c'est nécessairement que cpt < k, et donc on n'a pas fini. Et donc on rentre la boucle while qui elle va se terminer (puisqu'à un moment cpt vaudra k, il faut comprendre que la récursion n'est pas infinie, en aucun cas !).


Message édité par Profil supprimé le 06-12-2005 à 21:13:08
n°1260631
bugmenot
Posté le 06-12-2005 à 22:52:22  profilanswer
 

LOOOL, on ne marque pas les sommets visités, donc si y'a un arc reflexif, on va boucler sur un somment et aucun test dans ton algo permet de palier a ce probleme.
En bref, ton algo marche si on rajoute mon test, c'est tout ca que je constate, et je trouve ca tout a fait logique !

n°1260653
Profil sup​primé
Posté le 07-12-2005 à 00:18:35  answer
 

bugmenot a écrit :

LOOOL, on ne marque pas les sommets visités, donc si y'a un arc reflexif, on va boucler sur un somment et aucun test dans ton algo permet de palier a ce probleme.
En bref, ton algo marche si on rajoute mon test, c'est tout ca que je constate, et je trouve ca tout a fait logique !


 
Bon t'as rien compris tant pis pour toi, on pourra pas me reprocher de pas avoir essayé.
 
Ciao. :hello:

n°1260913
bugmenot
Posté le 07-12-2005 à 13:17:56  profilanswer
 

C'est bon lol j'ai compris ^^
 
En fait quand j'avais implémenté j'ai laissé if(est_terminal) quand i == k. Au lieu de faire un return(est_terminal).
 
Ton algo marchait donc bien ^^
 
Allé merci encore :p

mood
Publicité
Posté le   profilanswer
 


Aller à :
Ajouter une réponse
  FORUM HardWare.fr
  Programmation
  Algo

  Graphe Orienté : existence chemin longueur k ?

 

Sujets relatifs
[Javascript] longueur de Calque dynamiqueBesoin d'aide sur setInterval et javascript orienté objet...
Récupérer le chemin d'un dossier cherchéLongueur d'une comùande Awk
[SQL]comment tester l'existence d'une vue ?include et chemin absolu
récupérer le chemin du repertoire utilisateur [résolu]Chemin d'image dans excel
Sybase : Vérifier l'existence d'une table dans le tempdbCherche outil de gestion de bug orienté web
Plus de sujets relatifs à : Graphe Orienté : existence chemin longueur k ?


Copyright © 1997-2022 Hardware.fr SARL (Signaler un contenu illicite / Données personnelles) / Groupe LDLC / Shop HFR