0. Les données
![]() |
1. Dijkstra dans le métro
#define INFINITY LONG_MAX /* ====================================================================== */ /*! \fn void Dijkstra(graphe * g, int i) \param g (entrée) : un graphe pondéré. La pondération de chaque arc doit se trouver dans le champ \b v_arc de la structure \b cell . \param i (entrée) : un sommet de \b g. \brief calcule, pour chaque sommet x de g, la longueur d'un plus court chemin de i vers x. Cette longueur est stockée dans le champ \b v_sommets de \b g . */ void Dijkstra(graphe * g, int i) /* ====================================================================== */ { int n = g->nsom; boolean * S = EnsembleVide(n); int k, x, y; pcell p; TYP_VSOM vmin; S[i] = TRUE; for (k = 0; k < n; k++) g->v_sommets[k] = INFINITY; g->v_sommets[i] = 0; k = 1; x = i; while ((k < n) && (g->v_sommets[x] < INFINITY)) { for (p = g->gamma[x]; p != NULL; p = p->next) { /* pour tout y successeur de x */ y = p->som; if (!S[y]) { g->v_sommets[y] = min((g->v_sommets[y]),(g->v_sommets[x]+p->v_arc)); } // if (!S[y]) } // for p // extraire un sommet x hors de S de valeur g->v_sommets minimale vmin = INFINITY; for (y = 0; y < n; y++) if (!S[y]) if (g->v_sommets[y] <= vmin) { x = y; vmin = g->v_sommets[y]; } k++; S[x] = TRUE; } // while ((k < n) && (g->v_sommets[x] < INFINITY)) } /* Dijkstra() */Note : on peut ajouter un paramètre à cette procédure pour arrêter le travail dès qu'un sommet donné est atteint. Cela rendra plus efficace la recherche d'un plus court chemin d'un sommet d vers un sommet a.
2. Plus court chemin
/* ====================================================================== */ /*! \fn graphe * PCC(graphe * g, int i, int a) \param g (entrée) : un graphe pondéré. La pondération de chaque arc doit se trouver dans le champ \b v_arc de la structure \b cell . \param i (entrée) : un sommet de \b g. \param a (entrée) : un sommet de \b g. \return un plus court chemin de d vers a sous forme d'un graphe. \brief trouve un plus court chemin de d vers a, et retourne ce chemin sous forme d'un graphe. */ graphe *PCC(graphe * g, int i, int a) /* ====================================================================== */ { int n = g->nsom; boolean * S = EnsembleVide(n); int k, s, t; pcell p; TYP_VARC vmin, v; graphe * pcc = InitGraphe(n, n-1); /* pour le resultat */ graphe * g_1 = Symetrique(g); int n_som_explore = 0; // DIJKSTRA (avec arret des que le sommet a est atteint) S[i] = TRUE; for (k = 0; k < n; k++) g->v_sommets[k] = INFINITY; g->v_sommets[i] = 0; s = i; while ((s != a) && (g->v_sommets[s] < INFINITY)) { n_som_explore++; pcc->v_sommets[s] = 1; // pour le coloriage des sommets explores for (p = g->gamma[s]; p != NULL; p = p->next) { /* pour tout t successeur de s */ t = p->som; if (!S[t]) { v = g->v_sommets[s]+p->v_arc; if (g->v_sommets[t] > v) g->v_sommets[t] = v; } // if (!S[t]) } // for p // extraire un sommet s hors de S de valeur g->v_sommets minimale vmin = INFINITY; for (t = 0; t < n; t++) if (!S[t]) if (g->v_sommets[t] <= vmin) { s = t; vmin = g->v_sommets[t]; } S[s] = TRUE; } // while ((s != a) && (g->v_sommets[s] < INFINITY)) if (s != a) { printf("WARNING: pas de pcc trouve (s = %d , a = %d)\n", s, a); return NULL; } printf("pi(a) = %d\n", g->v_sommets[a]); printf("nb. sommets explores = %d\n", n_som_explore); // CONSTRUCTION DU PCC while (s != i) { for (p = g_1->gamma[s]; p != NULL; p = p->next) { /* pour tout t predecesseur de s */ t = p->som; if ((g->v_sommets[s]-g->v_sommets[t]) == p->v_arc) { AjouteArcValue(pcc, t, s, p->v_arc); s = t; break; } } // for p } TermineGraphe(g_1); for (k = 0; k < n; k++) { pcc->x[k] = g->x[k]; pcc->y[k] = g->y[k]; } return pcc; } /* PCC() */
Programme principal avec visualisation :
/* ====================================================================== */ void main(int argc, char **argv) /* ====================================================================== */ { graphe *g, *pcc; int na, ns; /* nombre d'arcs, nombre de sommets */ int d, a; if (argc != 4) { fprintf(stderr, "usage: %s graphe_value d a\n", argv[0]); exit(0); } g = ReadGraphe(argv[1]); /* lit le graphe a partir du fichier */ d = atoi(argv[2]); a = atoi(argv[3]); pcc = PCC(g, d, a); // genere une figure en PostScript EPSGraphe(pcc, "pcc.ps", 4, 2, 25, 0, 0, 1, 0); TermineGraphe(g); TermineGraphe(pcc); } /* main() */
![]() |
3. Variante Le plus simple est de modifier l'algorithme, mais attention, la stratégie ci-dessus pour construire le PCC ne marchera plus. Il faudra au cours de l'execution de Dijkstra mémoriser des pointeurs inverses (graphe auxiliaire).
4. Approche A*
#define INFINITY LONG_MAX #define ECHELLE 25.7 #define VITESSE 10.0 /* ====================================================================== */ /*! \fn graphe * PCCheuristique(graphe * g, int d, int a) \param g (entrée) : un graphe pondéré. La pondération de chaque arc doit se trouver dans le champ \b v_arc de la structure \b cell . les coordonnées cartesiennes de chaque sommet doivent se trouver dans les champs \b x et \b y de \b g. \param d (entrée) : un sommet de \b g. \param a (entrée) : un sommet de \b g. \return un plus court chemin de d vers a sous forme d'un graphe. \brief trouve un plus court chemin de d vers a, et retourne ce chemin sous forme d'un graphe. */ graphe * PCCheuristique(graphe * g, int d, int a) /* ====================================================================== */ { int n = g->nsom; boolean * S = EnsembleVide(n); int k, s, t, x; pcell p; TYP_VARC vmin, v, h; graphe * pcc = InitGraphe(n, n-1); /* pour le resultat */ graphe * g_1 = Symetrique(g); int n_som_explore = 0; // DIJKSTRA AVEC HEURISTIQUE S[d] = TRUE; for (k = 0; k < n; k++) g->v_sommets[k] = INFINITY; g->v_sommets[d] = 0; k = 1; s = d; while ((s != a) && (g->v_sommets[s] < INFINITY)) { n_som_explore++; pcc->v_sommets[s] = 1; // pour le coloriage des sommets explores for (p = g->gamma[s]; p != NULL; p = p->next) { /* pour tout t successeur de s */ t = p->som; if (!S[t]) { v = g->v_sommets[s]+p->v_arc; if (g->v_sommets[t] > v) g->v_sommets[t] = v; } // if (!S[t]) } // for p // extraire un sommet s hors de S de valeur g->v_sommets[s] + h(s) minimale, // avec h(s) = dist(s,a)*ECHELLE/VITESSE vmin = INFINITY; for (t = 0; t < n; t++) if (!S[t]) { h = (TYP_VARC)(dist(g->x[t],g->y[t],g->x[a],g->y[a]) * ECHELLE / VITESSE); v = g->v_sommets[t]; if (v < INFINITY) v += h; if (v <= vmin) { s = t; vmin = v; } } k++; S[s] = TRUE; } // while ((s != a) && (g->v_sommets[s] < INFINITY)) if (s != a) { printf("WARNING: pas de pcc trouve \n"); return pcc; } printf("pi(a) = %d\n", g->v_sommets[a]); printf("nb. sommets explores = %d\n", n_som_explore); // CONSTRUCTION DU PCC while (s != d) { for (p = g_1->gamma[s]; p != NULL; p = p->next) { /* pour tout t predecesseur de s */ t = p->som; if ((g->v_sommets[s]-g->v_sommets[t]) == p->v_arc) { AjouteArcValue(pcc, t, s, p->v_arc); s = t; break; } } // for p if (p == NULL) { printf("WARNING: pas de pcc trouve \n"); TermineGraphe(g_1); return pcc; } } TermineGraphe(g_1); for (k = 0; k < n; k++) { pcc->x[k] = g->x[k]; pcc->y[k] = g->y[k]; } return pcc; } /* PCCheuristique() */
Programme principal avec visualisation :
/* ====================================================================== */ void main(int argc, char **argv) /* ====================================================================== */ { graphe *g, *pcc; int na, ns; /* nombre d'arcs, nombre de sommets */ int d, a; if (argc != 4) { fprintf(stderr, "usage: %s graphe_value d a\n", argv[0]); exit(0); } g = ReadGraphe(argv[1]); /* lit le graphe a partir du fichier */ d = atoi(argv[2]); a = atoi(argv[3]); pcc = PCCheuristique(g, d, a); // genere une figure en PostScript EPSGraphe(pcc, "pcc.ps", 4, 2, 25, 0, 0, 1, 0); TermineGraphe(g); TermineGraphe(pcc); } /* main() */
![]() |