fd = fopen(argv[1], "r"); // ouverture fichier if (!fd) { fprintf(stderr, "cannot open file: %s\n", argv[1]); exit(0); } fscanf(fd, "%d", &ns); // lit le nombre de sommets dans le fichier na = (ns * (ns - 1)) / 2; // calcule le nombre d'arcs g = InitGraphe(ns, na); for (i = 0; i < ns; i++) fscanf(fd, "%lf %lf", &(g->x[i]), &(g->y[i])); fclose(fd); // construit le graphe des distances sur les sommets de g (antisymetrique et sans boucle) narc = 0; for (i = 0; i < ns; i++) for (j = i+1; j < ns; j++) { AjouteArc(g, i, j); g->tete[narc] = i; g->queue[narc] = j; g->v_arcs[narc] = -DistanceEuclidienne(g->x[i], g->y[i], g->x[j], g->y[j]); narc++; }Visualiser les graphes obtenus pour différentes valeurs de d. Peut-on trouver une valeur qui permette d'isoler les ``points de bruit'' des ``trajectoires de particules'', dans les trois images bs0, bs1, bs2 ?
Non.
Proposez (sans l'implémenter) une méthode pour trouver la valeur exacte de dmin pour un ensemble quelconque de points.
Partir du graphe vide sur N sommets, ajouter les arcs par poids croissant jusqu'à ce que le graphe obtenu soit connexe.
Complexité de la méthode ?
Tri en O(MlogM), avec M = nombre d'arcs = N * (N - 1) / 2, test connexité en O(n+m) pour n sommets et m arcs, d'où au pire O(MlogM + N+1+N+2+...+N+M) = O(MlogM + NM + M2) = O(M2)
/* ====================================================================== */
graphe * Kruskal1(graphe * g, graphe *g_1)
/* ====================================================================== */
{
int n = g->nsom;
int m = g->narc;
graphe * apm; /* pour le resultat */
graphe * apm_1; /* pour la detection de cycles */
int *A; /* tableau pour ranger les index des arcs */
int i, j, t, q;
boolean *Ct = EnsembleVide(n);
/* tri des arcs par poids croissant */
A = (int *)malloc(m * sizeof(int)); /* allocation index */
if (A == NULL)
{ fprintf(stderr, "Kruskal1 : malloc failed\n");
exit(0);
}
for (i = 0; i < m; i++) A[i] = i; /* indexation initiale */
TriRapideStochastique(A, g->v_arcs, 0, m-1);
/* construit le graphe resultat, initialement vide */
apm = InitGraphe(n, n-1);
apm_1 = InitGraphe(n, n-1);
/* Boucle sur les arcs pris par ordre decroissant:
on ajoute un arc dans apm, si cela ne cree pas un cycle dans apm.
Arret lorsque nb arcs ajoutes = n-1. */
j = 0;
i = m - 1;
while (j < n-1)
{
t = g->tete[A[i]]; q = g->queue[A[i]];
CompConnexe(apm, apm_1, t, Ct);
if (!Ct[q])
{
AjouteArc(apm, t, q);
AjouteArc(apm_1, q, t);
j++;
}
i--;
if (i < 0)
{ fprintf(stderr, "Kruskal1 : graphe d'origine non connexe\n");
exit(0);
}
}
if (g->x != NULL) // recopie les coordonnees des sommets pour l'affichage
for (i = 0; i < n; i++) { apm->x[i] = g->x[i]; apm->y[i] = g->y[i]; }
free(A);
free(Ct);
TermineGraphe(apm_1);
return apm;
} /* Kruskal1() */
Commentez les résultats obtenus sur les trois images bs0, bs1, bs2,
en particulier : quels sont les défauts de la méthode ?
Illustrez ces défauts par des exemples précis.
Deux types de défauts fréquents : les points de bruit qui créent des "branches", et ceux qui génèrent des déviations dans les trajectoires. Egalement, des déviations peuvent être constatées près des croisements de trajectoires, et de mauvaises connexions peuvent être effectuées entre deux trajectoires proches l'une de l'autre.
On se propose de redéfinir la nature des poids associés aux arcs, de façon à favoriser la sélection des arcs qui non seulement sont courts, mais sont également alignés avec des arcs adjacents. De plus, cette définition devra être relativement simple à implémenter.
Une idée qui "marche" : on considère le segment (i,j), avec i et j dans E, l'ensemble des points à relier. Soit i' le symétrique de i par rapport à j, et j' le symétrique de j par rapport à i. On peut prendre :
p = d(i,j) + alpha * [ min {d(i',k), k in E \ {i,j} } + min {d(j',k), k in E \ {i,j} } ]
Le point i' (idem j') peut être interprété comme une "prédiction" de l'emplacement d'un prochain point de trajectoire, si le segment (i,j) fait effectivement partie d'une trajectoire.
Le paramètre alpha permet de donner plus ou moins d'importance à la distance ou à la linéarité des trajectoires. Typiquement, alpha = 1.
Une branche est une partie de l'arbre située entre un point extrémité (un seul voisin) et un point multiple (ayant 3 voisins ou plus). On pourra éliminer les branches consituées de moins de K points, avec K entre 2 et 5 typiquement.