diff --git a/fourmi/fourmi.c b/fourmi/fourmi.c index aeec21544e53a3df471042dab62366cf4e3db3e8..462f51984d647bdbfdb523de9e436a8066962a95 100644 --- a/fourmi/fourmi.c +++ b/fourmi/fourmi.c @@ -1,13 +1,13 @@ #include "fourmi.h" -frmi create_fourmi() +frmi create_fourmi(int nb_sommet) { frmi fr = malloc(sizeof(f)); fr->path = malloc(sizeof(stack)); - stack_init(fr->path, 100); + stack_init(fr->path, nb_sommet); fr->distance = 0; - fr->ttl = 7; + fr->ttl = nb_sommet; return fr; } diff --git a/fourmi/fourmi.h b/fourmi/fourmi.h index 886cbb0150b8e960b47901d2d4879df93f40391c..5f1a362953e27ef009df6cebd5c0f5103b2d875a 100644 --- a/fourmi/fourmi.h +++ b/fourmi/fourmi.h @@ -19,7 +19,7 @@ typedef struct _fourmi typedef f *frmi; -frmi create_fourmi(); +frmi create_fourmi(int nb_sommet); void destroy_fourmi(frmi f); diff --git a/graphe.csv b/graphe.csv new file mode 100644 index 0000000000000000000000000000000000000000..3e4e0d2ce360dff13cebe646b1bc739bf05c53a8 --- /dev/null +++ b/graphe.csv @@ -0,0 +1,15 @@ +8 0 7 +0 1 2.0 +1 2 5.0 +2 1 5.0 +1 3 2.0 +3 1 1.0 +1 5 2.0 +2 3 1.0 +2 6 4.0 +3 4 4.0 +3 5 2.0 +3 6 3.0 +3 7 4.0 +4 7 2.0 +6 7 2.0 diff --git a/graphe/graphe.c b/graphe/graphe.c index 24e85e1e7de27a2e3f9e4bb9b0df35bb70ab0074..26d731d2d10cafdf02cb103c2cb1b3d4b72e2fd9 100644 --- a/graphe/graphe.c +++ b/graphe/graphe.c @@ -17,12 +17,13 @@ graph create_graph(int num, int fourmiliere, int nourriture) matrix *mat2 = malloc(sizeof(matrix)); matrix_init(mat2, num, num, 1); gr->pheromone = mat2; + //initialisation des variables de la matrice gr->foumiliere = fourmiliere; gr->nourriture = nourriture; return gr; } -int has_edge(graph g, int from_node, int to_node) +int has_edge(graph g, int from_node, int to_node) //permet de contrôle s'il y a une arête entre deux sommets { assert(g != NULL); assert(from_node < g->num); @@ -30,7 +31,7 @@ int has_edge(graph g, int from_node, int to_node) return g->edges->data[from_node][to_node]; } -void add_edge(graph g, int from_node, int to_node, double distance) +void add_edge(graph g, int from_node, int to_node, double distance) //permet d'ajouter une arête entre deux sommets { assert(g != NULL); assert(from_node < g->num); @@ -43,54 +44,65 @@ void add_edge(graph g, int from_node, int to_node, double distance) g->edges->data[from_node][to_node] = distance; } -int nb_voisin(graph g, int noeud) +graph main_create_graph(char *filename) //crée la matrice à partir d'un fichier csv { - int nb_noeud = 0; - for (int i = 0; i < g->num; i++) + graph g; + FILE *fp; + char buffer[100]; + + fp = fopen(filename, "r"); //ouverture fichier + //contrôle ouverture fichier + if (fp == NULL) { - if (has_edge(g, noeud, i)) - { - nb_noeud++; - } + printf("non ouvert\n"); } - return nb_noeud; -} -double ph_x_dist(graph g, int from, int to) -{ - double ph_x_dst = g->pheromone->data[from][to] * (1 / g->edges->data[from][to]); - return ph_x_dst; -} + int line_counter = 0; + while (fgets(buffer, 100, fp) != NULL) + { -stack ants_path(stack frmi, int path) -{ - stack_push(&frmi, path); - return frmi; -} + int a, b; + int c_int; + double c; -void pheromone_dissipation(graph g, int rho) -{ - for (int from = 0; from < g->num; from++) - { - for (int to = 0; to < g->num; to++) + //récupérer les données de la première ligne qui indique les informations de la matrice + if (line_counter == 0) { + sscanf(buffer, "%d %d %d", &a, &b, &c_int); + g = create_graph(a, b, c_int); + } - g->pheromone->data[from][to] = (1 - rho) * g->pheromone->data[from][to]; + else //récupère les données pour créer les arêtes en les sommets + { + sscanf(buffer, "%d %d %lf", &a, &b, &c); + add_edge(g, a, b, c); } + line_counter++; } + + fclose(fp); + return g; +} + +//afin d'alléger le code la fonction ci-dessous permet de calculer [phéromone * (1/arête)] +double ph_x_dist(graph g, int from, int to) +{ + double ph_x_dst = g->pheromone->data[from][to] * (1 / g->edges->data[from][to]); + return ph_x_dst; } int path_probability_taken(graph g, int noeud) { + // initialisation des tableaux à 0 double tab[g->num]; double tab_cumul[g->num]; - // initialisation des tableaux à 0 for (int k = 0; k < g->num; k++) { tab[k] = 0; tab_cumul[k] = 0; } // mettre les phéromones aux places du tableau pour le choix de l'indicee + //cette partie du code va créer un double qui sera le dénominateur pour nos calculs du chemin double somme_pour_proba = 0; for (int r = 0; r < g->num; r++) { @@ -99,14 +111,20 @@ int path_probability_taken(graph g, int noeud) somme_pour_proba += ph_x_dist(g, noeud, r); } } + //si la fourmi ne trouve pas de chemin, il y a une division par 0, mais surtout, elle ne peut choisir aucun chemin + //donc on retourne directement le noeud if (somme_pour_proba == 0) { return noeud; } + //A partir de là, le tableau qui stocke for (int i = 0; i < g->num; i++) { if (has_edge(g, noeud, i)) { + //calcul qui fait [(phéromone * (1/arête))] + // [-----------------------] //fraction + // [ 2 ] tab[i] = (g->pheromone->data[noeud][i] * (1.0 / g->edges->data[noeud][i])) / somme_pour_proba; } } @@ -126,10 +144,10 @@ int path_probability_taken(graph g, int noeud) } // calcul de la probabilité - double chemin_probabiliste = (double)rand() / (double)RAND_MAX; // nb entre 0 et 1 - for (int z = 0; z < g->num; z++) + double chemin_probabiliste = (double)rand() / (double)RAND_MAX; // nb entre 0 et 1 pour choisir le chemin à prendre + for (int z = 0; z < g->num; z++) //tester toutes les cases du tablea { - if (chemin_probabiliste <= tab_cumul[z]) + if (chemin_probabiliste <= tab_cumul[z]) //si le nombre probabilite est plus petit que la case du tableau, on retourne la case { return z; } @@ -139,7 +157,7 @@ int path_probability_taken(graph g, int noeud) double pheromone_depose(double distance) { - return 1.0000 / distance; + return 1.0000 / distance; //la phéromone est déposée en fonction de la longueur parcourue } int launch_colonization(graph g, int nb_fourmi, double rho) @@ -147,61 +165,52 @@ int launch_colonization(graph g, int nb_fourmi, double rho) int nb_fourmi_perdue = 0; for (int i = 0; i < nb_fourmi; i++) { - frmi f = create_fourmi(); - nb_fourmi_perdue += random_path(g, 0, rho, f); - destroy_fourmi(f); + frmi f = create_fourmi(g->num); //crée la fourmi + nb_fourmi_perdue += random_path(g, 0, rho, f); //appel la fonction principal à l'algorithme + destroy_fourmi(f); //détruit la fourmi } + //retourne le nombre de fourmi perdu return nb_fourmi_perdue; } int random_path(graph g, int noeud, double rho, frmi f) { - // f->ttl--; // condition d'arret si on arrive au noeud final ou si le ttl est à 0 if (noeud == g->nourriture) { f->depose_pheromone = 1; return 0; } - //////////////////////////////////////////////////////////////////////// + // calcul chemin aléatoire et renvoi l'indice du chemin à prendre int chemin_aleatoire; - // do - // { chemin_aleatoire = path_probability_taken(g, noeud); + //si le noeud retourné par le chemin est le même que celui par lequel il est rentré, c'est que le chemin n'as pas de sortie if (chemin_aleatoire == noeud) { f->depose_pheromone = 0; return 1; } - // } while (!has_edge(g, noeud, chemin_aleatoire)); - //----------------------------------------------------------------- - // stocke la distance parcourue dans la fourmi f->distance += g->edges->data[noeud][chemin_aleatoire]; // push le chemin parcouru dans la stack de la fourmi stack_push(f->path, noeud); stack_push(f->path, chemin_aleatoire); // la récursivité de l'algorithme (parcours graphe en profondeur) + //récursivité de l'algorithme int fourmi_perdu; fourmi_perdu = random_path(g, chemin_aleatoire, rho, f); - // if(f->ttl == 0) - // { - // return; - // } + if (f->depose_pheromone) { g->pheromone->data[noeud][chemin_aleatoire] = ((1 - rho) * g->pheromone->data[noeud][chemin_aleatoire]) + pheromone_depose(f->distance); } - // print_stack(*f->path); - // if(noeud == 0) - // { - // pheromone_dissipation(g); - // } + //permet le calcul du nombre de fourmi perdu récursivement if (fourmi_perdu) { return 1; } + //si la fourmi n'est pas perdu return 0; } @@ -229,7 +238,8 @@ void create_graph_vis(graph g) void shortest_path(graph g, frmi f, int noeud) { - if (noeud == g->nourriture) + f->ttl--; + if (noeud == g->nourriture || f->ttl == 0) { stack_push(f->path, noeud); return; @@ -238,8 +248,7 @@ void shortest_path(graph g, frmi f, int noeud) int index = 0; for (int i = 0; i < g->num; i++) { - - if (g->pheromone->data[noeud][i] > bigger || g->pheromone->data[noeud][i] != 1.0) + if (g->pheromone->data[noeud][i] > bigger && g->pheromone->data[noeud][i] != 1.0) { bigger = g->pheromone->data[noeud][i]; index = i; @@ -252,9 +261,39 @@ void shortest_path(graph g, frmi f, int noeud) } } -void display_graph_vis() +void export_shortest_path(graph g1, char *filename) { + int ecrit_chemin = 0; + int trash; + FILE *file = fopen(filename, "w"); + fprintf(file, "the shortest path is \n"); + frmi eclaireuse = create_fourmi(g1->num); + shortest_path(g1, eclaireuse, 0); + if (eclaireuse->path->top == g1->num - 1) + { + destroy_fourmi(eclaireuse); + printf("Aucun chemin ne peut être défini\n"); + return; + } + printf("shortest path is : "); + print_stack(*eclaireuse->path); + + while (!stack_is_empty(*eclaireuse->path)) + { + stack_pop(eclaireuse->path, &trash); + fprintf(file, "[%d]", eclaireuse->path->data[ecrit_chemin]); + ecrit_chemin++; + } + + printf("\n"); + destroy_fourmi(eclaireuse); + fclose(file); +} + +void display_graph_vis() +{ + //appel système pour lancer graphviz system("dot -Tpng -O test2.dot"); system("xdg-open test2.dot.png"); } diff --git a/graphe/graphe.h b/graphe/graphe.h index 5cd23bb592beefd18c2453075d356d5e069bf87d..dd884f874398e54bab492d531504d04dd7866074 100644 --- a/graphe/graphe.h +++ b/graphe/graphe.h @@ -1,5 +1,6 @@ #include <stdio.h> #include <stdbool.h> +#include <stdlib.h> #include <time.h> #include "../matrix/matrix.h" #include "../stack/stack.h" @@ -24,12 +25,16 @@ int has_edge(graph g, int from_node, int to_node); void add_edge(graph g, int from_node, int to_node, double distance); +void export_shortest_path(graph g1, char *filename); + int nb_voisin(graph g, int noeud); int random_path(graph g, int noeud, double rho, frmi f); int launch_colonization(graph g, int nb_fourmi, double rho); +graph main_create_graph(char *filename); + void shortest_path(graph g, frmi f, int noeud); // void first_walk(graph g, int index, stack *s); diff --git a/le_plus_court_chemin.txt b/le_plus_court_chemin.txt new file mode 100644 index 0000000000000000000000000000000000000000..c799b6b62927dc681c635a8a9e8622ded8f4a5c9 --- /dev/null +++ b/le_plus_court_chemin.txt @@ -0,0 +1,2 @@ +the shortest path is +[0][1][3][7] \ No newline at end of file diff --git a/main.c b/main.c index 3a8e6ae1c03750ee023a649c7a35dc4f6a0c67a8..c9a88df4502159cad90661d3835d42133e06c762 100644 --- a/main.c +++ b/main.c @@ -1,53 +1,27 @@ #include "graphe/graphe.h" -// #include "stack/stack.h" int main() { + //initialisation srand(time(NULL)); - graph g1 = create_graph(8, 0, 7); - stack stack; - stack_init(&stack, 50); - - // printf("\n"); - // matrix_print(*g1->pheromone); - // printf("\nadded edge\n\n"); - add_edge(g1, 0, 1, 2.0); - add_edge(g1, 1, 2, 5.0); - add_edge(g1, 1, 3, 2.0); - add_edge(g1, 1, 5, 2.0); - add_edge(g1, 2, 3, 1.0); - add_edge(g1, 3, 1, 1.0); - add_edge(g1, 2, 6, 4.0); - add_edge(g1, 3, 4, 4.0); - add_edge(g1, 3, 5, 2.0); - add_edge(g1, 3, 6, 3.0); - add_edge(g1, 3, 7, 4.0); - add_edge(g1, 4, 7, 2.0); - add_edge(g1, 6, 7, 2.0); int nb_fourmi_perdu = 0; - nb_fourmi_perdu = launch_colonization(g1, 1000000, 0.05); - + //création du graphe à partir d'un csv + graph g1 = main_create_graph("graphe.csv"); + //lancement de la colonisation des fourmis + nb_fourmi_perdu = launch_colonization(g1, 100000, 0.0001); + + //impression de la matrice des phéromones et des arêtes printf("\n length path matrix \n"); matrix_print(*g1->edges); printf("\npheromone matrix \n"); matrix_print(*g1->pheromone); printf("number of ants lost : %d\n", nb_fourmi_perdu); - // printf("\npheromone changed\n\n"); - // pheromone_dissipation(g1); - // matrix_print(*g1->pheromone); - // algorithme_des_fourmils(1, 3, g1); - + //détermine le plus court chemin avec une fourmi éclaireuse et sort le chemin dans un txt + export_shortest_path(g1, "le_plus_court_chemin.txt"); + //affichage du graphe dynamique avec l'utilisation de graphviz create_graph_vis(g1); display_graph_vis(); - frmi eclaireuse = create_fourmi(); - shortest_path(g1, eclaireuse, 0); - printf("shortest path is : "); - print_stack(*eclaireuse->path); - printf("\n"); - destroy_fourmi(eclaireuse); - + //libération de la mémoire destroy_graph(g1); - stack_destroy(&stack); - return 0; } \ No newline at end of file diff --git a/matrix/matrix.c b/matrix/matrix.c index 9e42e0bd3cf44d1dc75cf94e72c77b519b8ba902..8e762de15161ed6f24304c8ce3efe2e016df4051 100644 --- a/matrix/matrix.c +++ b/matrix/matrix.c @@ -35,14 +35,18 @@ error_code matrix_init(matrix *mat, int li, int co, double val) error_code matrix_print(const matrix mat) { - printf(" 0 1 2 3 4 5 6\n"); - printf(" - - - - -\n"); + printf(" "); + for(int i = 0; i < mat.cols; i++) + { + printf("%d ", i); + } + printf("\n - - - - -\n"); for(int row = 0; row < mat.rows; row++) { printf("%d | ", row); for(int col = 0; col < mat.cols; col++) { - printf("%f ", mat.data[row][col]); + printf("%0.2lf ", mat.data[row][col]); } printf("\n"); } @@ -61,123 +65,4 @@ error_code matrix_destroy(matrix *mat) mat->data = NULL; free(mat); return ok; -} - -// error_code matrix_init_from_array(matrix *mat, int li, int co, int data[], int s) //data [0] = mat->data[0][0] data[3] = mat->data[1][1] -// { -// if(s != li*co) -// { -// return err; -// } -// for(int row = 0; row < li; row++) -// { -// for(int col = 0; col < co; col++) -// { -// mat->data[row][col] = data[col + (row * li)]; -// } -// } -// return ok; -// } - -// error_code matrix_clone(matrix *cloned, const matrix mat) -// { -// for(int row = 0; row < mat.rows; row++) -// { -// for(int col = 0; col < mat.cols; col++) -// { -// cloned->data[row][col] = mat.data[row][col]; -// } -// } -// return ok; -// } - -// error_code matrix_transpose(matrix *transposed, const matrix mat) -// { -// for(int row = 0; row < mat.rows; row++) -// { -// for(int col = 0; col < mat.cols; col++) -// { -// transposed->data[col][row] = mat.data[row][col]; -// } -// } -// return ok; -// } -// error_code matrix_extract_submatrix(matrix *sub, const matrix mat,int li0, int li1, int co0, int co1) -// { -// int row = li1 - li0; -// int col = co1 - co0; -// if(row < sub->rows || col < sub->cols || row > sub->rows || col > sub->cols) -// { -// return err; -// } -// for(int i = li0; i < li1; i++) -// { -// for(int j = co0; j < co1; j++) -// { -// sub->data[i-li0][j-co0] = mat.data[i][j]; -// } -// } -// return ok; -// } - -// bool matrix_is_equal(matrix mat1, matrix mat2) -// { -// int estVrai = 1; -// assert(estVrai == 1); -// if(mat1.rows != mat2.rows) -// { -// return false; -// } -// else if(mat1.cols != mat2.cols) -// { -// return false; -// } -// else -// { -// for(int row = 0; row < mat1.rows; row++) -// { -// for(int col = 0; col < mat1.cols; col++) -// { -// if(mat1.data[row][col] != mat2.data[row][col]) -// { -// estVrai = 0; -// } - -// } -// } -// if(estVrai == 1) -// { -// return true; -// } -// else -// { -// return false; -// } -// } -// } - -// error_code matrix_get(int *elem, const matrix mat, int ix, int iy) -// { -// if(ix >= mat.rows || iy >= mat.cols) -// { -// return err; -// } -// else -// { -// *elem = mat.data[ix][iy]; -// return ok; -// } -// } - -// error_code matrix_set(matrix *mat, int ix, int iy, int elem) -// { -// if(ix >= mat->cols || iy >= mat->cols) -// { -// return err; -// } -// else -// { -// mat->data[ix][iy] = elem; -// return ok; -// } -// } \ No newline at end of file +} \ No newline at end of file diff --git a/stack/stack.c b/stack/stack.c index 0b5e8be4863ca13553fe567732b0595b151d904c..5416d7b0c443aa15062beb3ea080226987451b6b 100644 --- a/stack/stack.c +++ b/stack/stack.c @@ -28,7 +28,7 @@ void stack_push(stack *s, int value) { if(s->top == s->size-1) { - printf("stack full\n"); + // printf("stack full\n"); return; } else diff --git a/test2.dot b/test2.dot index 5e595614f29c606b37e86abcd568338d1b0e7d00..b55299990ce95960973609700cb1cdf4be876ac9 100644 --- a/test2.dot +++ b/test2.dot @@ -3,6 +3,7 @@ digraph Test { 1->2[penwidth=2, label= 5.000000] 1->3[penwidth=2, label= 2.000000] 1->5[penwidth=2, label= 2.000000] +2->1[penwidth=2, label= 5.000000] 2->3[penwidth=2, label= 1.000000] 2->6[penwidth=2, label= 4.000000] 3->1[penwidth=2, label= 1.000000] diff --git a/test2.dot.png b/test2.dot.png index 143ccff5fb274412510b4da8593c812dea32a8e7..0f3bd97af945318467c84b10d6e3a863bf6f41b2 100644 Binary files a/test2.dot.png and b/test2.dot.png differ diff --git a/tp_fourmi b/tp_fourmi index b8826e097769e2e968894456f51705e47cb2aaa7..d594449a5ff2623bfa3c7c14208f8eb65c05a803 100755 Binary files a/tp_fourmi and b/tp_fourmi differ