projet-reseaux-trophiques-equipe-3b / Algo_et_parcours_graphe / infoGraphe.c
infoGraphe.c
Raw
//
// 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");
}