//
// Created by titou on 28/11/2024.
//
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
#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; i<graphe->nbSommets; 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; i<graphe->nbSommets; 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; i<graphe->nbSommets; 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; i<graphe->nbSommets; 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");
}