// // Created by titou on 28/11/2024. // #include #include #include #include #include "infoGraphe.h" #include "../Bibliotheque_externe/cJSON.h" // Affiche les informations du graphe void afficherGraphe(Graphe* graphe) { printf("\033[38;2;51;159;67m"); printf("---------------------------------Sommets du reseau trophique-------------------------------------\n"); printf("\033[0m"); for (int i = 0; i < graphe->nbSommets; i++) { printf(" - %s : %s\n", graphe->noms[i], obtenirNomTypeEspece(graphe->tabEspece[i].type_espece)); } printf("\033[38;2;51;159;67m"); printf("-------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Relations trophiques---------------------------------\n"); printf("\033[0m"); for (int i = 0; i < graphe->nbSommets; i++) { for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[i][j]) { printf(" - %s -> %s : %d\n", graphe->noms[i], graphe->noms[j], graphe->capacites[i][j]); } } } printf("\033[38;2;51;159;67m"); printf("----------------------------------------------------------------------------------------\n"); printf("\033[0m"); printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Successeurs et predecesseurs---------------------------------\n"); printf("\033[0m"); for (int i = 0; i < graphe->nbSommets; i++) { printf("\n%s :\n Successeurs : ", graphe->noms[i]); int trouve = 0; for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[i][j]) { printf("%s ", graphe->noms[j]); trouve = 1; } } if (!trouve) printf("Aucun"); printf("\n Predecesseurs : "); trouve = 0; for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[j][i]) { printf("%s ", graphe->noms[j]); trouve = 1; } } if (!trouve) printf("Aucun"); printf("\n"); } printf("\033[38;2;51;159;67m"); printf("--------------------------------------------------------------------------------------------\n"); printf("\033[0m"); } // Détermine le type d'une espèce int determinerTypeEspece(Graphe* graphe, int index, espece* especes) { for (int i = 0; i < graphe->nbSommets; i++) { if (graphe->capacites[i][index]) { return especes[i].type_espece + 1; } } return PRODUCTEUR_PRIMAIRE; } const char* obtenirNomTypeEspece(int type) { switch (type) { case PRODUCTEUR_PRIMAIRE: return "Producteur primaire"; case CONSOMMATEUR_PRIMAIRE: return "Consommateur primaire"; case CONSOMMATEUR_SECONDAIRE: return "Consommateur secondaire"; case CONSOMMATEUR_TERTIAIRE: return "Consommateur tertiaire"; default: return "Inconnu"; } } // Fonction pour afficher la complexité du réseau void afficherComplexiteReseau(Graphe* graphe) { printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Complexite du reseau trophique---------------------------------\n"); printf("\033[0m"); // Nombre d'espèces printf(" - Nombre d'especes : %d\n", graphe->nbSommets); // Hauteur trophique int hauteur = calculerHauteurTrophique(graphe); printf(" - Hauteur trophique : %d\n", hauteur); // Densité de liaison double densite = calculerDensiteLiaison(graphe); printf(" - Densite de liaison : %.3f\n", densite); // Distribution des degrés afficherDistributionDegres(graphe); printf("\033[38;2;51;159;67m"); printf("-------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); } int* obtenirDegresEntrants(Graphe* graphe) { int* degresEntrants = calloc(graphe->nbSommets, sizeof(int)); for (int i = 0; i < graphe->nbSommets; i++) { for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[j][i] != 0) { degresEntrants[i]++; } } } return degresEntrants; } int* obtenirDegresSortants(Graphe* graphe) { int* degresSortants = calloc(graphe->nbSommets, sizeof(int)); for (int i = 0; i < graphe->nbSommets; i++) { for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[i][j] != 0) { degresSortants[i]++; } } } return degresSortants; } void afficherDistributionDegres(Graphe* graphe) { int* degresEntrants = obtenirDegresEntrants(graphe); int* degresSortants = obtenirDegresSortants(graphe); printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Distribution des degres---------------------------------\n"); printf("\033[0m"); for (int i = 0; i < graphe->nbSommets; i++) { printf(" - %s : Degres entrants = %d, Degres sortants = %d\n", graphe->noms[i], degresEntrants[i], degresSortants[i]); } printf("\033[38;2;51;159;67m"); printf("-------------------------------------------------------------------------------------------\n"); printf("\033[0m"); free(degresEntrants); free(degresSortants); } // Fonction pour calculer la densité de liaison double calculerDensiteLiaison(Graphe* graphe) { int nbLiens = 0; for (int i = 0; i < graphe->nbSommets; i++) { for (int j = 0; j < graphe->nbSommets; j++) { if (graphe->capacites[i][j]) { nbLiens++; } } } int nbLiensPossibles = graphe->nbSommets * (graphe->nbSommets - 1); return (double)nbLiens / nbLiensPossibles; } // Fonction pour calculer la hauteur trophique int calculerHauteurTrophique(Graphe* graphe) { int hauteurtrophique = 0; for(int i = 0; inbSommets; i++){ if(graphe->tabEspece[i].type_espece>hauteurtrophique){ hauteurtrophique = graphe->tabEspece[i].type_espece; } } return hauteurtrophique; } // Libérer la mémoire des espèces void libererEspeces(espece* especes) { if (especes) { espece* courant = especes; while (courant->name) { free(courant->name); // seg fault courant++; } free(especes); } } // Libérer la mémoire du graphe void libererGraphe(Graphe* graphe) { if (graphe) { for (int i = 0; i < graphe->nbSommets; i++) { free(graphe->noms[i]); free(graphe->capacites[i]); } free(graphe->noms); free(graphe->capacites); free(graphe); } } // Fonction pour créer le graphe avec les espèces Graphe* creerGrapheAvecEspeces(cJSON * json) { espece * especes = NULL; // Récupérer les nœuds cJSON* nodes = cJSON_GetObjectItem(json, "nodes"); if (!cJSON_IsArray(nodes)) { printf("Le champ 'nodes' n'est pas un tableau.\n"); cJSON_Delete(json); return NULL; } // Allouer le graphe Graphe* graphe = malloc(sizeof(Graphe)); graphe->nbSommets = cJSON_GetArraySize(nodes); graphe->ecosysteme = malloc(strlen(cJSON_GetObjectItem(json, "ecosystem")->valuestring) + 1); graphe->noms = malloc(graphe->nbSommets * sizeof(char*)); graphe->capacites = malloc(graphe->nbSommets * sizeof(int*)); graphe->tabEspece = NULL; // Allouer le tableau d'espèces especes = malloc(graphe->nbSommets * sizeof(espece)); graphe->ecosysteme = strdup( cJSON_GetObjectItem(json, "ecosystem")->valuestring); // Initialiser la matrice de capacités for (int i = 0; i < graphe->nbSommets; i++) { graphe->capacites[i] = calloc(graphe->nbSommets, sizeof(int)); } // Récupérer les liens cJSON* links = cJSON_GetObjectItem(json, "links"); if (!cJSON_IsArray(links)) { printf("Le champ 'links' n'est pas un tableau.\n"); cJSON_Delete(json); return NULL; } // Relations trophiques cJSON* link; cJSON_ArrayForEach(link, links) { int source = cJSON_GetObjectItem(link, "source")->valueint - 1; int target = cJSON_GetObjectItem(link, "target")->valueint - 1; int relation = cJSON_GetObjectItem(link, "relation")->valueint ; // Mettre à jour la matrice de capacités graphe->capacites[source][target] = relation; } // Parcourir et stocker les nœuds int index = 0; cJSON* node; cJSON_ArrayForEach(node, nodes) { int id = cJSON_GetObjectItem(node, "id")->valueint; const char* name = cJSON_GetObjectItem(node, "name")->valuestring; const char* couleur = cJSON_GetObjectItem(node, "couleur")->valuestring; const char* type = cJSON_GetObjectItem(node, "type")->valuestring; const char* emoji = cJSON_GetObjectItem(node, "emoji")->valuestring; // Stocker les informations de l'espèce especes[index].id = id; especes[index].vivante = 1; especes[index].name = strdup(name); especes[index].type_espece = determinerTypeEspece(graphe, index, especes); especes[index].population = NULL; especes[index].tCroissance = cJSON_GetObjectItem(node, "tauxC")->valuedouble; especes[index].couleur = strdup(couleur); // Stocker le nom dans le graphe graphe->noms[index] = strdup(name); index++; } // Libérer la mémoire du JSON graphe->tabEspece = especes; return graphe; } void RechercheProducteurPrimaire(Graphe* graphe){ int* degresEntrants = obtenirDegresEntrants(graphe); printf("\033[38;2;51;159;67m"); printf("-----------------Liste des Producteur primaires-----------------"); printf("\033[0m"); for(int i = 0; inbSommets; i++){ if(degresEntrants[i] == 0){ printf("\n%s\n", graphe->tabEspece[i].name); } } printf("\033[38;2;51;159;67m"); printf("----------------------------------------------------------------\n\n"); printf("\033[0m"); free(degresEntrants); } void RechercheSansPredateur(Graphe* graphe){ int* degresSortant = obtenirDegresSortants(graphe); printf("\033[38;2;51;159;67m"); printf("---------------Liste des especes sans predateurs----------------"); printf("\033[0m"); for(int i = 0; inbSommets; i++){ if(degresSortant[i] == 0){ printf("\n%s\n", graphe->tabEspece[i].name); } } printf("\033[38;2;51;159;67m"); printf("----------------------------------------------------------------\n\n"); printf("\033[0m"); free(degresSortant); } void RechercheSommetPart(Graphe* graphe, int nbdegresSortant, int nbdegresEntrant){ int* degresSortant = obtenirDegresSortants(graphe); int* degresEntrants = obtenirDegresEntrants(graphe); printf("\033[38;2;51;159;67m"); printf("----------Liste des especes a %d proies et %d predateur-----------\n", nbdegresEntrant, nbdegresSortant); printf("\033[0m"); for(int i = 0; inbSommets; i++){ if((degresSortant[i] == nbdegresSortant) && (degresEntrants[i] == nbdegresEntrant)){ printf("\n%s\n", graphe->tabEspece[i].name); } } printf("\033[38;2;51;159;67m"); printf("----------------------------------------------------------------\n\n"); printf("\033[0m"); free(degresSortant); free(degresEntrants); } void AffichageSommetSpecifique(Graphe* graphe){ int nbdegreentrant = 0; int nbdegresortant = 0; printf("\033[38;2;51;159;67m"); printf("---------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); printf("\nChosir un sommet a afficher\n"); printf("\nNombre de proies : \n"); scanf("%d", &nbdegreentrant); printf("\nNombre de predateurs : \n"); scanf("%d", &nbdegresortant); RechercheSommetPart(graphe, nbdegresortant, nbdegreentrant); } void affichageSommPart(Graphe* graphe){ int choix = 1; printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Affichage de sommet specifique---------------------------------\n"); printf("\033[0m"); RechercheProducteurPrimaire(graphe); RechercheSansPredateur(graphe); while(choix == 1){ printf("\nVoulez vous choisir d autres sommets specifique : \n"); printf("\n1 - Oui\n"); printf("\n2 - Non\n"); scanf("%d", &choix); if(choix == 1){ AffichageSommetSpecifique(graphe); } } } void construireChaineAlimentaire(Graphe* graphe, int especeIndex, char* base, int* niveauTrophique, int niveau) { strcat(base, graphe->noms[especeIndex]); if (niveau > *niveauTrophique) { *niveauTrophique = niveau; } int predecesseursTrouves = 0; for (int i = 0; i < graphe->nbSommets; i++) { if (graphe->capacites[i][especeIndex] != 0) { predecesseursTrouves = 1; char newBase[150]; strcpy(newBase, base); strcat(newBase, "<-"); construireChaineAlimentaire(graphe, i,newBase, niveauTrophique, niveau + 1); } } if (!predecesseursTrouves) { printf("%s\n", base); printf("Hauteur trophique : %d\n", niveau); } } void afficherChainesAlimentaires(Graphe* graphe, const char* nomEspece) { int especeIndex = -1; for (int i = 0; i < graphe->nbSommets; i++) { if (strcmp(graphe->noms[i], nomEspece) == 0) { especeIndex = i; break; } } if (especeIndex == -1) { printf("Espece %s non trouvee.\n", nomEspece); return; } printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Chaines alimentaires dont %s depend---------------------------------\n", nomEspece); printf("\033[0m"); int niveauTrophique = 1; char base[150] = ""; construireChaineAlimentaire(graphe, especeIndex, base, &niveauTrophique, 1); printf("\033[38;2;51;159;67m"); printf("--------------------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); } void AnalyseHauteurTrophique(Graphe* graphe){ int choix = 1; char nomEspece[30]; printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Etude de hauteur trophique d'une espece---------------------------------\n"); printf("\033[0m"); while(choix == 1){ printf("\nVoulez vous etudier la heuteur trophique d une autre espece ?"); printf("\n1 - Oui\n"); printf("\n2 - Non\n"); scanf("%d", &choix); if(choix == 1){ printf("\nEntrez le nom de l espece : "); scanf("%s", nomEspece); afficherChainesAlimentaires(graphe, nomEspece); } } printf("\033[38;2;51;159;67m"); printf("-----------------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); } //-------------------------------ANALYSE DE LA CONEXITE----------------------------------------- // Création d'une matrice non orientée int** creerMatriceNonOriente(Graphe* graphe) { if (!graphe || !graphe->capacites) { fprintf(stderr, "Graphe ou matrice invalide.\n"); return NULL; } int n = graphe->nbSommets; int** matrice = malloc(n * sizeof(int*)); for (int i = 0; i < n; i++) { matrice[i] = calloc(n, sizeof(int)); for (int j = 0; j < n; j++) { matrice[i][j] = graphe->capacites[i][j] || graphe->capacites[j][i]; } } return matrice; } // Parcours en profondeur (DFS) void dfs(int** matrice, int* visite, int taille, int noeud) { visite[noeud] = 1; for (int i = 0; i < taille; i++) { if (matrice[noeud][i] && !visite[i]) { dfs(matrice, visite, taille, i); } } } // Vérifie si un graphe est connexe int estConnexe(Graphe* graphe) { int n = graphe->nbSommets; int** matrice = creerMatriceNonOriente(graphe); int* visite = calloc(n, sizeof(int)); dfs(matrice, visite, n, 0); for (int i = 0; i < n; i++) { if (!visite[i]) { free(visite); for (int j = 0; j < n; j++) free(matrice[j]); free(matrice); return false; } } free(visite); for (int i = 0; i < n; i++) free(matrice[i]); free(matrice); return true; } // Fonction pour tester la connexité après suppression de sommets int estConnexeApresSuppression(Graphe* graphe, int* sommetsSuppr, int nbSuppr) { int n = graphe->nbSommets; int** matrice = creerMatriceNonOriente(graphe); int* visite = calloc(n, sizeof(int)); int* supprimes = calloc(n, sizeof(int)); // Tableau pour marquer les sommets supprimés // Marquer les sommets comme supprimés for (int k = 0; k < nbSuppr; k++) { supprimes[sommetsSuppr[k]] = 1; for (int j = 0; j < n; j++) { matrice[sommetsSuppr[k]][j] = 0; // Supprime la ligne matrice[j][sommetsSuppr[k]] = 0; // Supprime la colonne } } // Trouver un sommet valide (non supprimé) comme point de départ int depart = -1; for (int i = 0; i < n; i++) { if (!supprimes[i]) { depart = i; break; } } // Si tous les sommets sont supprimés if (depart == -1) { free(visite); free(supprimes); for (int i = 0; i < n; i++) free(matrice[i]); free(matrice); return true; // Rien à connecter, considérer comme connexe } // Lancer le DFS à partir d'un sommet non supprimé dfs(matrice, visite, n, depart); // Vérifier si tous les sommets non supprimés sont atteignables for (int i = 0; i < n; i++) { if (!visite[i] && !supprimes[i]) { free(visite); free(supprimes); for (int j = 0; j < n; j++) free(matrice[j]); free(matrice); return false; // Le graphe est déconnecté } } free(visite); free(supprimes); for (int i = 0; i < n; i++) free(matrice[i]); free(matrice); return true; } // Fonction utilitaire pour générer toutes les combinaisons de sommets void genererCombinaisons(int* arr, int n, int k, int index, int* data, int i, int* minK, Graphe* graphe) { if (index == k) { // Si une combinaison rend le graphe non connexe, on met à jour minK if (!estConnexeApresSuppression(graphe, data, k)) { *minK = k; } return; } if (i >= n) return; // Inclure arr[i] dans la combinaison data[index] = arr[i]; genererCombinaisons(arr, n, k, index + 1, data, i + 1, minK, graphe); // Exclure arr[i] de la combinaison genererCombinaisons(arr, n, k, index, data, i + 1, minK, graphe); } // Calculer la k-conexité correcte int calculerKConnexite(Graphe* graphe) { int n = graphe->nbSommets; int* sommets = malloc(n * sizeof(int)); for (int i = 0; i < n; i++) sommets[i] = i; // Tester pour k = 1 for (int i = 0; i < n; i++) { int combinaison[1] = {i}; if (!estConnexeApresSuppression(graphe, combinaison, 1)) { free(sommets); return 1; // k = 1 } } // Tester pour k = 2 for (int i = 0; i < n; i++) { for (int j = i + 1; j < n; j++) { int combinaison[2] = {i, j}; if (!estConnexeApresSuppression(graphe, combinaison, 2)) { free(sommets); return 2; // k = 2 } } } free(sommets); return n; // Si aucun test ne déconnecte le graphe } // Affiche l'analyse de connexité void afficherAnalyseConnexite(Graphe* graphe) { printf("\033[38;2;51;159;67m"); printf("\n---------------------------------Analyse de la connexité du graphe---------------------------------\n"); printf("\033[0m"); if (estConnexe(graphe)) { printf("Le graphe est connexe.\n"); printf("La k-connexité du graphe est : %d\n", calculerKConnexite(graphe)); } else { printf("Le graphe n'est pas connexe.\n"); } printf("\033[38;2;51;159;67m"); printf("----------------------------------------------------------------------------------------------------\n"); printf("\033[0m"); }