diff --git a/README.md b/README.md index 64f93f31d12999c8fd6d2e56707ff0406cd7c0dd..f5b831d08cc313310d6339279fccf06ac29bb356 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ Le réseau est extrait de DBLP et disponible sur SNAP. GraphStream permet de mesurer de nombreuses caractéristiques d'un réseau. La plupart de ces mesures sont implantées comme des méthodes statiques dans la classe Toolkit. Elles vous seront très utiles par la suite. +# TP 1: ## 1- Tout d'abord : @@ -36,10 +37,19 @@ double clusteringCoefficient = Toolkit.averageClusteringCoefficient(graph); ## 3- Autres mesures Voyons maintenant si le graphe est connexe : -- Le réseau est-il connexe ? : Toolkit.isConnected renvoie Oui +- Le réseau est-il connexe ? : Oui + +```java +boolean isConnected = Toolkit.isConnected(graph); +``` + - Degré moyen minimal pour qu'un graphe aléatoire soit connexe : 12.666909386951092 -## Distribution des Degrés +```java +double minAverageDegreeForConnectivity = Math.log(nodeCount); +``` + +## 4- Distribution des Degrés Exportation des données : Les degrés des nœuds sont exportés dans le fichier degree_distribution.txt. @@ -69,4 +79,594 @@ nous observons une ligne droite ce qui nous dit que la distribution suit une loi une ligne droite est observée, cela indique une loi de puissance. - Comparaison avec la distribution de Poisson : Superposer la distribution de Poisson avec ⟨k⟩. -![Distribution des degrés](dd_dblp.png) +![Dblp](dd_dblp.png) + + +## 5- Distance moyenne et distribution des distances + + +Distance moyenne de notre réseau: 6.700611818856679 + +```java +double degreeAverage = Toolkit.averageDegree(graph); +double NetworkDistance = Math.log(graph.getNodeCount()) / Math.log(degreeAverage); +System.out.println("Distance moyenne dans notre réseau : " + NetworkDistance); +``` + + +- L'hypothèse des six degrés de séparation se confirme-t-elle ? + +Oui, l'hypothèse des six degrés de séparation est confirmée : la distance moyenne entre les nœuds est proche de 6. + +- Est-ce qu'il s'agit d'un réseau petit monde ? + +Le réseau montre des propriétés caractéristiques des réseaux "petit monde" : une distance moyenne faible et un clustering élevé. + +- Quelle sera la distance moyenne dans un réseau aléatoire avec les mêmes caractéristiques ? + +J'ai calculé la distance moyenne d'un réseau aléatoire de même taille et de même degré moyen que j'ai généré avec randomGenerator de graphstream et ça nous donne à peu prés la même chose + +Distance moyenne du réseau Aléatoire : 6.70193902051403 + +```java +double degreeAverage = Toolkit.averageDegree(randomGraph); +double NetworkDistance = Math.log(randomGraph.getNodeCount()) / Math.log(degreeAverage); +System.out.println("Distance moyenne du réseau Aléatoire : " + NetworkDistance); +``` +Tracer les distributions des distances : + + +![Distribution des distances](distance_distribution.png) + + +- Analyse de la courbe des distances moyennes : + +Forme en cloche avec une décroissance symétrique de chaque côté. + +La courbe montre un pic central autour de 6. Cela suggère que la distance moyenne entre +les paires de nœuds est proche de cette valeur. Cela soutient l'hypothèse des six degrés de séparation, car la majorité des distances sont à 6 ou moins. + +Décroissance rapide : Les distances très petites et très grandes sont rares, tandis que les distances proches de la moyenne sont les plus fréquentes. + + +- Formulez une hypothèse sur la loi de cette distribution. + +On conclut donc que la forme de la distribution est proche d'une loi normale, ce qui est souvent observé dans les réseaux petits mondes. + + +## 6- Générer deux graphes de même taille et de même degré : + +1 - le graphe aléatoire: + +Cette méthode génère un graphe aléatoire basé sur les propriétés d'un graphe d'entrée initialGraph, à l'aide d'un générateur de graphes aléatoires de GraphStream. +Le graphe généré a un nombre total de nœuds fixé (N = 317080) et un degré moyen similaire à celui de initialGraph. + + + + +```java +public static Graph createRandomGraph(Graph initialGraph) { + + double averageDegree = Toolkit.averageDegree(initialGraph); + + Generator generator = new RandomGenerator(averageDegree, false); + Graph graphAlea = new SingleGraph("graphe aléatoire"); + int N = 317080; + + // graphe aléatoire générer de taille N + generator.addSink(graphAlea); + generator.begin(); + while (graphAlea.getNodeCount() < N) { + generator.nextEvents(); + } + generator.end(); + if (graphAlea.getNodeCount() == N) { + System.out.println("Graph aléatoire générer !"); + } + + + return graphAlea; + } + +``` + +Les caractéristiques de ce graphe sont : + +Réseau aléatoire : +- Nombre de nœuds : 317080 +- Nombre de liens : 1049473 +- Degré moyen : 6.61961030960083 +- Coefficient de clustering : 4.364833098823207E-5 + +j'ai aussi calculé les degrés de distribution à l'échelle linéaire et à l'échelle log-log + +- Linéaire : + +![Distribution des degrés](degree_distribution_random.png) + +- Log-log : + +![Distribution des degrés](degree_distribution_loglog_random.png) + + +2 - Le graphe Barabàsi-Albert: + +Cette méthode génère un graphe Barabási-Albert en utilisant le graphe d'entrée initialGraph comme référence. +Le modèle Barabási-Albert est un modèle de croissance qui suit le principe de l'attachement préférentiel : +les nouveaux nœuds ont une probabilité plus élevée de se connecter aux nœuds déjà fortement connectés (hubs). +Ce modèle permet de générer des graphes sans échelle, +où la distribution des degrés suit une loi de puissance. + + + +```java + +public static Graph generateBarabasiAlbertGraph(Graph initialGraph) { + int nodeCount = initialGraph.getNodeCount(); + double averageDegree = Toolkit.averageDegree(initialGraph); + + Graph barabasiGraph = new SingleGraph("Barabasi-Albert Network"); + BarabasiAlbertGenerator generator = new BarabasiAlbertGenerator((int) averageDegree); + generator.addSink(barabasiGraph); + generator.begin(); + while (barabasiGraph.getNodeCount() < nodeCount) { + generator.nextEvents(); + } + generator.end(); + return barabasiGraph; +} + + +``` + + +Les caractéristiques de ce graphe sont : + +Nombre de nœuds : 317080 +Nombre de liens : 1108680 +Degré moyen : 6.993061542510986 +Coefficient de clustering : 4.235788849759945E-4 + + +j'ai aussi calculé les degrés de distribution à l'échelle linéaire et à l'échelle log-log + +- Linéaire : + +![Distribution des degrés](degree_distribution_ba.png) + +- Log-log : + +![Distribution des degrés](degree_distribution_loglog_BA.png) + + + +Comparaison des réseaux générés +En théorie, les deux modèles de réseaux, aléatoire +(Erdős-Rényi) et Barabási-Albert, se distinguent +par leur structure et leur comportement. + +En théorie : + +- Réseau aléatoire : + +Les liens sont créés de manière totalement aléatoire entre les nœuds. +Le degré moyen suit une distribution de Poisson : +la plupart des nœuds ont un degré proche de +la moyenne, et il y a très peu de nœuds avec un +degré beaucoup plus élevé ou plus faible. + +Le coefficient de clustering est très faible car les +triangles (groupes de trois nœuds connectés entre +eux) sont rares dans ce type de réseau. + + +- Réseau Barabási-Albert : + +Ce modèle suit une loi de puissance : quelques +nœuds, appelés hubs, ont un très grand nombre de +connexions, tandis que la majorité des nœuds sont +faiblement connectés. + +Le coefficient de clustering est plus élevé que +dans un réseau aléatoire, car les hubs favorisent +la connexion entre plusieurs nœuds, augmentant la +probabilité de former des triangles. + + + +Les résultats expérimentaux correspondent à ces prédictions théoriques comme le démontre le tableau ci-dessous : + + +| Propriété | Réseau Aléatoire | Réseau Barabási-Albert | +|---------------------------|-----------------------------|-------------------| +| **Nombre de nœuds** | 317 080 | 317 080 | +| **Nombre de liens** | 1 049 907 | 1 108 082 | +| **Degré moyen** | 6,6223 | 6,9893 | +| **Clustering** | 3.57 × 10⁻⁵ | 3.82 × 10⁻⁴ | + +Le faible clustering du réseau random et le clustering un peu plus élevé du réseau BA sont conformes à ce qu'on attend. +En résumé, ces expériences confirment que le modèle Barabási-Albert est plus adapté pour modéliser des réseaux où les hubs +jouent un rôle important. + +## 7- La méthode Copie : +La méthode de copie modifiée sert à générer un réseau en imitant des caractéristiques des réseaux réels, comme la formation +de triangles et un haut coefficient de clustering. + +Comment ça fonctionne ? + +- On commence par choisir un nœud au hasard. + +À chaque étape : + +- Un nouveau nœud est ajouté au réseau. + +- Ce nouveau nœud choisit au hasard un nœud existant dans le réseau, qu’on appelle nœud cible. + +- Il parcourt les voisins du nœud cible. Pour chaque voisin, il a une probabilité p (par exemple, p=0,5) de se connecter à ce voisin. + +- À la fin, il se connecte obligatoirement au nœud cible. + +Pourquoi c'est intéressant ? + +La probabilité p permet de créer des connexions locales, ce qui augmente le coefficient de clustering. + +ATTENTION : Le nouveau nœud ne se connecte pas à tous les voisins du nœud cible, mais seulement à certains d’entre eux, +en fonction de la probabilité p. +Cette méthode garde le réseau connexe grâce à la connexion obligatoire au nœud cible. + +Voici comment je m'y suis prise : + +```java + +public static Graph genererGrapheCopie(int nombreNoeuds, double probabilitéCopie) { +Graph grapheCopie = new SingleGraph("GrapheCopie"); +Random aleatoire = new Random(); + + // Ajouter un premier nœud pour démarrer le réseau + grapheCopie.addNode("0"); + + for (int i = 1; i < nombreNoeuds; i++) { + Node nouveauNoeud = grapheCopie.addNode(String.valueOf(i)); + + // Choisir un nœud aléatoire existant + Node noeudCible = grapheCopie.getNode(aleatoire.nextInt(grapheCopie.getNodeCount())); + + // Parcourir les voisins de noeudCible + noeudCible.edges().forEach(edge -> { + if (edge != null) { // Vérifier que l'arête n'est pas null + Node voisin = edge.getOpposite(noeudCible); + + // Connecter au voisin avec probabilité p + String edgeIdVoisin = nouveauNoeud.getId() + "-" + voisin.getId(); + if (aleatoire.nextDouble() < probabilitéCopie && grapheCopie.getEdge(edgeIdVoisin) == null) { + grapheCopie.addEdge(edgeIdVoisin, nouveauNoeud, voisin); + } + } + }); + + // Connecter le nouveau nœud au nœud cible + String edgeIdCible = nouveauNoeud.getId() + "-" + noeudCible.getId(); + if (grapheCopie.getEdge(edgeIdCible) == null) { + grapheCopie.addEdge(edgeIdCible, nouveauNoeud, noeudCible); + } + } + + return grapheCopie; + } + + +``` +Voici les résultats après éxecution du code : + +- Nombre de nœuds : 317080 +- Nombre de liens : 3392116 +- Degré moyen : 21.395963668823242 +- Coefficient de clustering : 0.44452828185775123 + +On remarque bien que le degré moyen est très élevé, mais aussi le coeff de clustring. + + + + + +# TP 2 : + +## 1 - Taux de propagation et seuil épidémique du réseau ainsi que le seuil théorique d'un réseau aléatoire du même degré moyen : + +Avant de commencer, il faut savoir que ce modèle est un SIS (Susceptible-Infected-Susceptible) +##### Dans un modèle SIS: + +chaque individu de la population peut être dans l’un des deux états suivants : + +- Susceptible (S) : +L'individu est en bonne santé mais peut être infecté. +- Infecté (I) : +L'individu est malade et peut transmettre l'infection. + +##### Dynamique des transitions +- Un individu susceptible (S) peut devenir infecté (I) après un contact avec une personne infectée, avec une probabilité appelée taux d'infection (β). +- Un individu infecté (I) peut se rétablir et redevenir susceptible (S) avec une probabilité appelée taux de récupération (μ). + +La principale caractéristique du modèle SIS est que les individus infectés ne développent pas d'immunité après récupération, ce qui signifie qu'ils peuvent être réinfectés. + + +- Taux de propagation : + +###### τ = β/μ + +avec β = 1 (une personne est infécté a partir du moment où elle reçoit un mail) + +et μ = 0.5 ( il mettent à jour leurs anti-virus 2 fois par mois donc 2 semaines sur 4) + + +ce qui nous donne un taux de propagation (τ) : 2.0 que j'ai calculé comme suit : + + +```java +double infectionProbability = 1.0; // β = 1 +double recoveryProbability = 0.5; // μ = 0.5 + + double tau = infectionRate / recoveryRate; // Taux de propagation +``` + +- Seuil épidémique : + +###### c = < k > / + +avec : degré moyen (le nombre moyen de connexions par nœud) + +et : moyenne des carrés des degrés des nœuds. + +ce qui nous donne un seuil épidémique réel (c_réel) de 0.04598472436222584 que j'ai calculé comme suit : + + +```java +double cReal = avgDegree / avgDegreeSquared; +``` +```java + +private static double calculateSquaredAverageDegree(Graph graph) { +double totalDegreeSquared = 0; +for (Node node : graph) { +totalDegreeSquared += Math.pow(node.getDegree(), 2); // Somme des carrés des degrés +} +return totalDegreeSquared / graph.getNodeCount(); // Moyenne des carrés des degrés +} +``` + +enfin, le seuil théorique : + +```java +double cTheoretical = 1.0 / (avgDegree + 1); // Seuil théorique pour un réseau aléatoire avec normalisation +``` +ce qui nous donne un seuil théorique de 0.13119762993051035. + +on constate que la maladie persiste La maladie persiste dans le réseau réel (τ > c_réel) et que le réseau réel est plus vulnérable que le réseau aléatoire (c_réel < c_théorique). + +## 2 - Simulation des 3 scénario : + +Voici les paramètres de ma méthode de simulation : il y'en a 6 : + +- Graph graph : Le graphe +- double infectionRate : La probabilité qu'un nœud infecté transmette la maladie à un voisin susceptible. +- double recoveryRate : La probabilité qu'un nœud infecté se rétablisse et redevienne susceptible. +- int days : Le nombre total de jours pendant lesquels la simulation est exécutée. +- double immunizationFraction : La fraction de nœuds ou voisins à immuniser avant le début de la simulation. +- boolean randomImmunization : Détermine la stratégie d'immunisation : + +true : Immunisation aléatoire. + +false : Immunisation sélective (immuniser un voisin d'un nœud sélectionné). + +Cette partie là concerne les deux scénario où il y'a des gens à immuniser (scénario 2 et 3) +ceci est assuré grâce au premier if, et le deuxième if nous permet de savoir si c'est une random immunisation donc le scénario 2 (on convint 50% des gens à mettre à jour leurs anti-virus) où la condition nous retournera true car c'est un boolean +ou non et on passera au else donc le scénario 3 (on convint 50% des gens à convaincre un de leurs voisins). + +```java +// Immunization + if (immunizationFraction > 0) { + int immunizedCount = (int) (immunizationFraction * graph.getNodeCount()); + if (randomImmunization) { + // Immunisation aléatoire : immuniser des nœuds directement + for (int i = 0; i < immunizedCount; i++) { + Node node = graph.getNode(random.nextInt(graph.getNodeCount())); + node.setAttribute("immune", true); + } + } else { + // Immunisation sélective : immuniser un voisin pour 50% des nœuds existants + List nodes = new ArrayList<>( graph.nodes().toList()); + + // Calculer le nombre de nœuds à immuniser (50% des nœuds existants) + int nodesToImmunize = (int) (immunizationFraction * nodes.size()); + + // Mélanger les nœuds pour garantir une sélection aléatoire + Collections.shuffle(nodes, random); + + // Sélectionner les premiers `nodesToImmunize` nœuds et immuniser un voisin pour chacun + for (int i = 0; i < nodesToImmunize; i++) { + Node node = nodes.get(i); + + // Vérifier que le nœud a des voisins + if (node.getDegree() > 0) { + // Prendre un voisin aléatoire + List neighbors = node.neighborNodes().toList(); + Node neighbor = neighbors.get(random.nextInt(neighbors.size())); + + // Immuniser ce voisin + neighbor.setAttribute("immune", true); + } + } + + } + + } +``` + +viens maintenant la simulation (c'est un peu là ou tout se déroule y compris le scénario 1) + +On commence par infecter un patient qu'on appellera patient 0. + +- infectedCount : Nombre de nœuds infectés au cours de la journée actuelle. +- totalNonImmune : Nombre total de nœuds non immunisés dans le graphe +(c'est-à-dire les nœuds susceptibles ou infectés). + +- Exclusion des nœuds immunisés : Les nœuds avec l'attribut immune ne participent pas à la propagation. + +###### Propagation (S→I) : +- Les nœuds infectés propagent l'infection à leurs voisins susceptibles avec une probabilité définie par infectionRate. +- Les nœuds susceptibles infectés reçoivent un état futur "infected" stocké dans nextState. +###### Récupération (I→S) : +- Les nœuds infectés peuvent récupérer avec une probabilité définie par recoveryRate et sont marqués comme "susceptible" dans nextState. + + +On fait ensuite une mise à jour des états des nœuds, Les changements d’état sont appliqués après chaque jour. + +Résultats : La fraction de nœuds infectés est calculée chaque jour et retournée à la fin. + +```java +// Infect patient zero +Node patientZero = graph.getNode(new Random().nextInt(graph.getNodeCount())); + patientZero.setAttribute("state", "infected"); + + +// Simulation +for (int day = 0; day < days; day++) { +int infectedCount = 0; +int totalNonImmune = 0; + + for (Node node : graph) { + if (!node.hasAttribute("immune")) { + totalNonImmune++; + if (node.getAttribute("state").equals("infected")) { + infectedCount++; + for (Node neighbor : node.neighborNodes().toList()) { + if (!neighbor.hasAttribute("immune") && neighbor.getAttribute("state").equals("susceptible") && random.nextDouble() < infectionRate) { + neighbor.setAttribute("nextState", "infected"); + } + } + if (random.nextDouble() < recoveryRate) { + node.setAttribute("nextState", "susceptible"); + } + } + } + } + + // mise à jour de l'état des noeuds + for (Node node : graph) { + if (node.hasAttribute("nextState")) { + node.setAttribute("state", node.getAttribute("nextState")); + node.removeAttribute("nextState"); + } + } + infectedFractions[day] = (double) infectedCount / totalNonImmune; + } + + return infectedFractions; + } +``` +#### on obtient ces courbes qui montrent bien l'efficacité de l'immunisation séléctive. + +![propagation simulation](propagationsimulation.png) + + +## 3 - Le degré moyen des groupes 0 et 1 : + +Il faut savoir que le groupe 0 sont les nœuds choisis aléatoirement et le groupe un de leurs voisins. + +Resumé : +- Groupe 0 => 50% des nœuds [non immunisé] +- Groupe 1 => 1 voisin de ces nœuds [immunisés] + +voici comment j'ai procédé : + +```java +// Appliquer une immunisation aléatoire (immuniser 50 % des nœuds) + Set immune = new HashSet<>(); + Random random = new Random(); + int immuneCount = (int) (0.5 * graph.getNodeCount()); // Immuniser 50 % des nœuds + List nodes = new ArrayList<>(graph.nodes().toList()); + Collections.shuffle(nodes, random); + for (int i = 0; i < immuneCount; i++) { + Node node = nodes.get(i); + node.setAttribute("immune", true); // Marquer comme immunisé + immune.add(node); + } + + // Groupes + Set group0 = new HashSet<>(); // Groupe 0 : 50 % des nœuds non immunisés + Set group1 = new HashSet<>(); // Groupe 1 : Un voisin immunisé de chaque nœud du Groupe 0 + + // Sélectionner 50 % des nœuds non immunisés pour le Groupe 0 + List nonImmuneNodes = new ArrayList<>(); + for (Node node : graph) { + if (!immune.contains(node)) { // Nœuds non immunisés + nonImmuneNodes.add(node); + } + } + Collections.shuffle(nonImmuneNodes, random); // Mélanger les nœuds non immunisés + int targetCount = (int) (0.5 * nonImmuneNodes.size()); // 50 % des nœuds non immunisés + for (int i = 0; i < targetCount; i++) { + group0.add(nonImmuneNodes.get(i)); // Ajouter au groupe 0 + } + + // Pour chaque nœud du Groupe 0, ajouter un voisin immunisé au Groupe 1 + for (Node node : group0) { + List neighbors = node.neighborNodes().toList(); + for (Node neighbor : neighbors) { + if (immune.contains(neighbor)) { // Vérifier si le voisin est immunisé + group1.add(neighbor); // Ajouter un seul voisin immunisé au groupe 1 + break; // Sortir de la boucle après avoir trouvé un voisin immunisé + } + } + } + + // Calcul du degré moyen pour le Groupe 0 (non immunisé) + double totalDegreeGroup0 = 0; + for (Node node : group0) { + totalDegreeGroup0 += node.getDegree(); + } + double averageDegreeGroup0 = group0.isEmpty() ? 0 : totalDegreeGroup0 / group0.size(); + System.out.printf("Degré moyen (Groupe 0 - Non immunisé) : %.9f%n", averageDegreeGroup0); + + // Calcul du degré moyen pour le Groupe 1 (voisins immunisés) + double totalDegreeGroup1 = 0; + for (Node node : group1) { + totalDegreeGroup1 += node.getDegree(); + } + double averageDegreeGroup1 = group1.isEmpty() ? 0 : totalDegreeGroup1 / group1.size(); + System.out.printf("Degré moyen (Groupe 1 - Voisins immunisés) : %.9f%n", averageDegreeGroup1); +``` + +Immunisation aléatoire : + +50 % des nœuds du graphe sont sélectionnés de manière aléatoire pour être immunisés. + +Ces nœuds sont marqués avec l'attribut "immune" et ajoutés à un ensemble immune. + + +###### Groupe 0 (non immunisé) : + +les nœuds non immunisés forment le groupe 0. + +Ces nœuds représentent une population aléatoire non immunisée dans le graphe. + +###### Groupe 1 (voisins immunisés) : + +Pour chaque nœud du Groupe 0, on cherche un voisin immunisé (parmi ceux marqués "immune"). +Ce voisin immunisé est ajouté au Groupe 1. + +Chaque nœud du Groupe 0 est associé à un seul voisin immunisé. + + +Voici les résultats : + +- Degré moyen (Groupe 0 - Non immunisé) : 6,601652580 +- Degré moyen (Groupe 1 - Voisins immunisés) : 14,067850086 + +La différence entre les degrés moyens reflète l’efficacité de l’immunisation sélective : + +###### Immunisation aléatoire : +Le degré moyen est similaire au degré moyen global du graphe. +###### Immunisation sélective : +Le degré moyen est nettement plus élevé, car les voisins des hubs +(nœuds critiques) sont ciblés, ce qui fragmente davantage le réseau. \ No newline at end of file diff --git a/barabasi_degree_distribution.txt b/barabasi_degree_distribution.txt new file mode 100644 index 0000000000000000000000000000000000000000..f71e80d10f88e93bfbb3c2bbe0aee7a8a9e98c21 --- /dev/null +++ b/barabasi_degree_distribution.txt @@ -0,0 +1,321 @@ +# Degree Probability +1 0.11089945755014508 +2 0.11121798915100291 +3 0.11159959631638704 +4 0.11104768512678188 +5 0.11085845843320298 +6 0.11048631260249779 +7 0.0743944745805475 +8 0.05184496026239435 +9 0.03817333165131828 +10 0.028141163113409865 +11 0.021619149741390186 +12 0.017200706446322694 +13 0.013725242840923427 +14 0.011113914469534502 +15 0.009294184432950674 +16 0.007584836634287877 +17 0.006354863126024978 +18 0.005364576762962029 +19 0.0045982086539674534 +20 0.004197678819225432 +21 0.0035038476094361045 +22 0.0031001639964677685 +23 0.0027595559480257346 +24 0.0022770278793995207 +25 0.001986880282578529 +26 0.0018008073672259367 +27 0.0016368108994575502 +28 0.001510659770404945 +29 0.0014412766494260123 +30 0.00125520373407342 +31 0.0011984357259997476 +32 0.0010722845969471427 +33 0.001006055254194525 +34 8.672890122366595E-4 +35 8.199823388419326E-4 +36 7.915983348050965E-4 +37 6.843698751103823E-4 +38 6.812160968840671E-4 +39 6.2760186703671E-4 +40 5.172196291156806E-4 +41 4.478365081367478E-4 +42 5.01450737984105E-4 +43 3.847609436104453E-4 +44 4.1314494764728145E-4 +45 3.8160716538413017E-4 +46 3.595307177999243E-4 +47 3.343004919894033E-4 +48 3.469156048946638E-4 +49 2.6491737101047054E-4 +50 2.996089314999369E-4 +51 2.4599470165257976E-4 +52 2.712249274631008E-4 +53 2.239182540683739E-4 +54 2.2707203229468904E-4 +55 2.2707203229468904E-4 +56 2.0184180648416804E-4 +57 1.860729153525924E-4 +58 1.9238047180522266E-4 +59 1.8291913712627727E-4 +60 1.8922669357890754E-4 +61 1.5453513308944116E-4 +62 1.5768891131575627E-4 +63 1.4507379841049577E-4 +64 1.5453513308944116E-4 +65 1.2615112905260502E-4 +66 1.0092090324208402E-4 +67 1.2615112905260502E-4 +68 9.461334678945377E-5 +69 1.103822379210294E-4 +70 7.569067743156301E-5 +71 1.0407468146839915E-4 +72 7.884445565787813E-5 +73 9.461334678945377E-5 +74 9.461334678945377E-5 +75 8.830579033682351E-5 +76 8.199823388419326E-5 +77 6.307556452630251E-5 +78 7.884445565787813E-5 +79 6.307556452630251E-5 +80 7.253689920524788E-5 +81 6.307556452630251E-5 +82 4.4152895168411754E-5 +83 6.307556452630251E-5 +84 6.307556452630251E-5 +85 6.307556452630251E-5 +86 5.9921786299987385E-5 +87 5.3614229847357136E-5 +88 4.099911694209663E-5 +89 5.046045162104201E-5 +90 4.7306673394726886E-5 +91 4.7306673394726886E-5 +92 6.938312097893276E-5 +93 4.099911694209663E-5 +94 2.5230225810521005E-5 +95 5.676800807367226E-5 +96 2.838400403683613E-5 +97 3.469156048946638E-5 +98 4.4152895168411754E-5 +99 3.7845338715781505E-5 +100 4.7306673394726886E-5 +101 1.5768891131575628E-5 +102 4.7306673394726886E-5 +103 4.099911694209663E-5 +104 3.1537782263151255E-5 +105 2.838400403683613E-5 +106 1.5768891131575628E-5 +107 2.2076447584205877E-5 +108 3.7845338715781505E-5 +109 2.5230225810521005E-5 +110 3.1537782263151255E-5 +111 2.838400403683613E-5 +112 2.838400403683613E-5 +113 2.2076447584205877E-5 +114 1.5768891131575628E-5 +115 2.5230225810521005E-5 +116 1.8922669357890752E-5 +117 2.5230225810521005E-5 +118 1.5768891131575628E-5 +119 1.8922669357890752E-5 +120 6.307556452630251E-6 +121 1.8922669357890752E-5 +122 2.838400403683613E-5 +123 1.8922669357890752E-5 +124 2.5230225810521005E-5 +125 1.8922669357890752E-5 +126 6.307556452630251E-6 +127 1.5768891131575628E-5 +128 9.461334678945376E-6 +129 1.5768891131575628E-5 +130 2.5230225810521005E-5 +131 2.2076447584205877E-5 +132 1.5768891131575628E-5 +133 1.2615112905260503E-5 +134 1.5768891131575628E-5 +135 1.5768891131575628E-5 +136 1.2615112905260503E-5 +137 1.2615112905260503E-5 +138 9.461334678945376E-6 +139 3.1537782263151255E-5 +140 9.461334678945376E-6 +141 2.838400403683613E-5 +142 6.307556452630251E-6 +143 1.2615112905260503E-5 +144 1.5768891131575628E-5 +145 1.5768891131575628E-5 +146 6.307556452630251E-6 +147 9.461334678945376E-6 +148 3.1537782263151257E-6 +149 6.307556452630251E-6 +150 9.461334678945376E-6 +151 9.461334678945376E-6 +152 9.461334678945376E-6 +153 9.461334678945376E-6 +154 1.8922669357890752E-5 +155 3.1537782263151257E-6 +156 6.307556452630251E-6 +157 6.307556452630251E-6 +158 1.5768891131575628E-5 +159 6.307556452630251E-6 +160 6.307556452630251E-6 +161 9.461334678945376E-6 +162 6.307556452630251E-6 +163 9.461334678945376E-6 +164 3.1537782263151257E-6 +165 1.2615112905260503E-5 +166 3.1537782263151257E-6 +167 6.307556452630251E-6 +168 3.1537782263151257E-6 +169 3.1537782263151257E-6 +170 9.461334678945376E-6 +171 3.1537782263151257E-6 +172 3.1537782263151257E-6 +173 2.2076447584205877E-5 +174 1.8922669357890752E-5 +175 6.307556452630251E-6 +176 9.461334678945376E-6 +177 3.1537782263151257E-6 +178 3.1537782263151257E-6 +180 1.2615112905260503E-5 +181 9.461334678945376E-6 +182 1.2615112905260503E-5 +183 6.307556452630251E-6 +184 1.2615112905260503E-5 +185 3.1537782263151257E-6 +186 9.461334678945376E-6 +188 6.307556452630251E-6 +190 6.307556452630251E-6 +191 9.461334678945376E-6 +192 3.1537782263151257E-6 +193 6.307556452630251E-6 +195 6.307556452630251E-6 +196 3.1537782263151257E-6 +197 3.1537782263151257E-6 +198 3.1537782263151257E-6 +199 6.307556452630251E-6 +200 3.1537782263151257E-6 +202 6.307556452630251E-6 +203 3.1537782263151257E-6 +204 1.2615112905260503E-5 +205 3.1537782263151257E-6 +206 3.1537782263151257E-6 +207 3.1537782263151257E-6 +208 3.1537782263151257E-6 +209 6.307556452630251E-6 +210 6.307556452630251E-6 +211 6.307556452630251E-6 +213 6.307556452630251E-6 +214 6.307556452630251E-6 +215 6.307556452630251E-6 +217 6.307556452630251E-6 +221 3.1537782263151257E-6 +222 6.307556452630251E-6 +223 3.1537782263151257E-6 +226 3.1537782263151257E-6 +228 3.1537782263151257E-6 +230 9.461334678945376E-6 +231 9.461334678945376E-6 +232 3.1537782263151257E-6 +233 3.1537782263151257E-6 +234 3.1537782263151257E-6 +235 3.1537782263151257E-6 +236 3.1537782263151257E-6 +238 3.1537782263151257E-6 +240 3.1537782263151257E-6 +242 1.2615112905260503E-5 +243 3.1537782263151257E-6 +244 6.307556452630251E-6 +247 3.1537782263151257E-6 +249 3.1537782263151257E-6 +250 6.307556452630251E-6 +254 9.461334678945376E-6 +255 3.1537782263151257E-6 +256 3.1537782263151257E-6 +259 6.307556452630251E-6 +263 3.1537782263151257E-6 +264 3.1537782263151257E-6 +265 6.307556452630251E-6 +266 3.1537782263151257E-6 +267 6.307556452630251E-6 +269 3.1537782263151257E-6 +270 3.1537782263151257E-6 +272 3.1537782263151257E-6 +273 6.307556452630251E-6 +278 9.461334678945376E-6 +281 3.1537782263151257E-6 +283 3.1537782263151257E-6 +284 3.1537782263151257E-6 +285 6.307556452630251E-6 +286 3.1537782263151257E-6 +288 6.307556452630251E-6 +292 3.1537782263151257E-6 +293 9.461334678945376E-6 +294 3.1537782263151257E-6 +295 6.307556452630251E-6 +298 3.1537782263151257E-6 +299 3.1537782263151257E-6 +300 3.1537782263151257E-6 +303 3.1537782263151257E-6 +304 3.1537782263151257E-6 +306 6.307556452630251E-6 +310 3.1537782263151257E-6 +317 3.1537782263151257E-6 +318 3.1537782263151257E-6 +326 3.1537782263151257E-6 +334 3.1537782263151257E-6 +336 3.1537782263151257E-6 +338 3.1537782263151257E-6 +341 3.1537782263151257E-6 +342 3.1537782263151257E-6 +345 6.307556452630251E-6 +347 3.1537782263151257E-6 +348 3.1537782263151257E-6 +349 3.1537782263151257E-6 +358 3.1537782263151257E-6 +368 3.1537782263151257E-6 +373 3.1537782263151257E-6 +375 3.1537782263151257E-6 +376 3.1537782263151257E-6 +378 3.1537782263151257E-6 +391 3.1537782263151257E-6 +411 3.1537782263151257E-6 +420 3.1537782263151257E-6 +428 6.307556452630251E-6 +430 6.307556452630251E-6 +432 3.1537782263151257E-6 +444 3.1537782263151257E-6 +453 3.1537782263151257E-6 +460 3.1537782263151257E-6 +468 3.1537782263151257E-6 +473 3.1537782263151257E-6 +481 3.1537782263151257E-6 +488 3.1537782263151257E-6 +490 3.1537782263151257E-6 +562 3.1537782263151257E-6 +591 3.1537782263151257E-6 +596 3.1537782263151257E-6 +597 3.1537782263151257E-6 +601 3.1537782263151257E-6 +639 3.1537782263151257E-6 +644 3.1537782263151257E-6 +648 3.1537782263151257E-6 +654 3.1537782263151257E-6 +666 3.1537782263151257E-6 +672 3.1537782263151257E-6 +676 3.1537782263151257E-6 +697 3.1537782263151257E-6 +701 3.1537782263151257E-6 +702 3.1537782263151257E-6 +771 3.1537782263151257E-6 +846 3.1537782263151257E-6 +961 3.1537782263151257E-6 +974 3.1537782263151257E-6 +1074 3.1537782263151257E-6 +1097 3.1537782263151257E-6 +1107 3.1537782263151257E-6 +1159 3.1537782263151257E-6 +1166 3.1537782263151257E-6 +1303 3.1537782263151257E-6 +1329 3.1537782263151257E-6 +1527 3.1537782263151257E-6 diff --git a/comparison_results.txt b/comparison_results.txt new file mode 100644 index 0000000000000000000000000000000000000000..c9221006655be092bd51a23e054f41a199b4a47b --- /dev/null +++ b/comparison_results.txt @@ -0,0 +1,13 @@ +Comparaison des réseaux générés : + +Réseau aléatoire : +Nombre de noeuds : 317080 +Nombre de liens : 1049119 +Degré moyen : 6,6174 +Coefficient de clustering : 0,0000 + +Réseau Barabási-Albert : +Nombre de noeuds : 317080 +Nombre de liens : 1110120 +Degré moyen : 7,0021 +Coefficient de clustering : 0,0004 diff --git a/degree_distribution.txt b/degree_distribution.txt index 2a0dc15dcd74393aee66f5ae902c62e747d4486f..cc8161b750efe17c455b7e509d9ad7b6b6eb0267 100644 --- a/degree_distribution.txt +++ b/degree_distribution.txt @@ -1,4 +1,4 @@ -Degree Probability +# Degree Probability 1 0.13618329759051342 2 0.18562507884445567 3 0.1566071653841302 diff --git a/degree_distribution_ba.png b/degree_distribution_ba.png new file mode 100644 index 0000000000000000000000000000000000000000..883079fea5fc3e3a51416601508896acf92bc3d9 Binary files /dev/null and b/degree_distribution_ba.png differ diff --git a/degree_distribution_linear_BA.png b/degree_distribution_linear_BA.png new file mode 100644 index 0000000000000000000000000000000000000000..c6988e6347208b1a0c6e2d82875af033d65ca0ef Binary files /dev/null and b/degree_distribution_linear_BA.png differ diff --git a/degree_distribution_linear_random.png b/degree_distribution_linear_random.png new file mode 100644 index 0000000000000000000000000000000000000000..ad8f5777f7a05f0c6fb3e196472cc356aa9edc4c Binary files /dev/null and b/degree_distribution_linear_random.png differ diff --git a/degree_distribution_loglog_ba.png b/degree_distribution_loglog_ba.png new file mode 100644 index 0000000000000000000000000000000000000000..b227f7a66d18ed61ec4663ea985deb79bdc0f72c Binary files /dev/null and b/degree_distribution_loglog_ba.png differ diff --git a/degree_distribution_loglog_random.png b/degree_distribution_loglog_random.png new file mode 100644 index 0000000000000000000000000000000000000000..7f204c92b52510d160261b87f343f6cc6943bb12 Binary files /dev/null and b/degree_distribution_loglog_random.png differ diff --git a/degree_distribution_random.png b/degree_distribution_random.png new file mode 100644 index 0000000000000000000000000000000000000000..bb8ee152951c117a44b27a1344be6909dd082038 Binary files /dev/null and b/degree_distribution_random.png differ diff --git a/distance_distribution.dat b/distance_distribution.dat new file mode 100644 index 0000000000000000000000000000000000000000..2ec3ea4331f86a5c6fbad7dc84004ab3aa12c8bd --- /dev/null +++ b/distance_distribution.dat @@ -0,0 +1,20 @@ +1 0.000020 +2 0.000237 +3 0.002877 +4 0.026896 +5 0.131700 +6 0.284280 +7 0.284713 +8 0.164319 +9 0.069059 +10 0.024703 +11 0.008037 +12 0.002319 +13 0.000624 +14 0.000163 +15 0.000041 +16 0.000010 +17 0.000002 +18 0.000000 +19 0.000000 +20 0.000000 diff --git a/distance_distribution.png b/distance_distribution.png new file mode 100644 index 0000000000000000000000000000000000000000..b65ee0ca1864821236af569bbc09e546ff970a5c Binary files /dev/null and b/distance_distribution.png differ diff --git a/distance_distribution.txt b/distance_distribution.txt deleted file mode 100644 index 6b0d1ba81b8bbb6c1a6c47091e55b80bf2bdf594..0000000000000000000000000000000000000000 --- a/distance_distribution.txt +++ /dev/null @@ -1,22 +0,0 @@ -Distance Frequency -0 1000 -1 6586 -2 78287 -3 959632 -4 8613239 -5 41171567 -6 89177656 -7 90856123 -8 52934122 -9 22176664 -10 7738891 -11 2381840 -12 710135 -13 202360 -14 54352 -15 13569 -16 3211 -17 613 -18 131 -19 21 -20 1 diff --git a/pom.xml b/pom.xml index 4c9df9c77a2d2d2a133af63c854e6209eee07102..63fb3ad3f68ab0f8d4b25d8c0aba8543c001b862 100644 --- a/pom.xml +++ b/pom.xml @@ -25,6 +25,18 @@ 2.0 + + + + org.apache.maven.plugins + maven-compiler-plugin + + 17 + 17 + + + + 11 diff --git a/propagation_simulation.png b/propagation_simulation.png new file mode 100644 index 0000000000000000000000000000000000000000..64a44dfdba22358217f815d1d9b10bf1a06c0ad3 Binary files /dev/null and b/propagation_simulation.png differ diff --git a/propagation_simulation_2.png b/propagation_simulation_2.png new file mode 100644 index 0000000000000000000000000000000000000000..eee56a31e553cea793986a39c8743012adf8a716 Binary files /dev/null and b/propagation_simulation_2.png differ diff --git a/propagation_simulation_3.png b/propagation_simulation_3.png new file mode 100644 index 0000000000000000000000000000000000000000..c6be5c473e1f8aecbff18dbd998e8822190e5487 Binary files /dev/null and b/propagation_simulation_3.png differ diff --git a/propagationsimulation.png b/propagationsimulation.png new file mode 100644 index 0000000000000000000000000000000000000000..3b0a698e7eb356cf98c9b9be73edeafe5b460804 Binary files /dev/null and b/propagationsimulation.png differ diff --git a/random_degree_distribution.txt b/random_degree_distribution.txt new file mode 100644 index 0000000000000000000000000000000000000000..d350b6989344fde13c413b1103a7e5358b8b78a8 --- /dev/null +++ b/random_degree_distribution.txt @@ -0,0 +1,49 @@ +# Degree Probability +0 0.008404818973129809 +1 0.03444871956604011 +2 0.07259997476977419 +3 0.1079853664690299 +4 0.12453639460073168 +5 0.12400971363693705 +6 0.11061877128800303 +7 0.09228901223665952 +8 0.07288066103191623 +9 0.057897060678693074 +10 0.04512741264034313 +11 0.03466948404188217 +12 0.026867036709978556 +13 0.020619402043648292 +14 0.015699508010596695 +15 0.01218304528825533 +16 0.009209032420840167 +17 0.007045540557587991 +18 0.005219502964551532 +19 0.004049451242588621 +20 0.003062318657751987 +21 0.0024788696858836887 +22 0.0020373407341995713 +23 0.001302510407468147 +24 9.80825028384004E-4 +25 9.05134350952441E-4 +26 6.969849880156427E-4 +27 4.951431815314747E-4 +28 4.0052983474202095E-4 +29 2.996089314999369E-4 +30 2.491484798788949E-4 +31 1.6715024599470166E-4 +32 1.103822379210294E-4 +33 1.5768891131575627E-4 +34 6.622934275261763E-5 +35 6.622934275261763E-5 +36 3.469156048946638E-5 +37 3.7845338715781505E-5 +38 2.5230225810521005E-5 +39 6.307556452630251E-6 +40 9.461334678945376E-6 +41 6.307556452630251E-6 +42 3.1537782263151257E-6 +43 1.8922669357890752E-5 +44 6.307556452630251E-6 +47 6.307556452630251E-6 +48 6.307556452630251E-6 +51 3.1537782263151257E-6 diff --git a/scenario1_no_control.dat b/scenario1_no_control.dat new file mode 100644 index 0000000000000000000000000000000000000000..226310d3f26e6c5682fd19fc1375954e6ae64fd1 --- /dev/null +++ b/scenario1_no_control.dat @@ -0,0 +1,90 @@ +1 3.1537782263151257E-6 +2 9.461334678945376E-6 +3 1.0722845969471427E-4 +4 0.0014412766494260123 +5 0.016346032546991296 +6 0.14012552037340734 +7 0.46108553046549766 +8 0.616002270720323 +9 0.6426327740633279 +10 0.6503059164879526 +11 0.6505771414154157 +12 0.6537813800933518 +13 0.650700138766242 +14 0.6522770278793996 +15 0.6523243345527943 +16 0.6531443168916362 +17 0.6540052983474202 +18 0.6512268197300366 +19 0.6527248643875363 +20 0.6530812413271099 +21 0.6525577141415415 +22 0.6508042134477103 +23 0.6535700769521887 +24 0.6518071149236786 +25 0.6526081745931626 +26 0.6522202598713258 +27 0.6529834742020941 +28 0.6525671754762206 +29 0.6525766368108995 +30 0.6513498170808629 +31 0.6532452377948783 +32 0.6521130314116311 +33 0.651501198435726 +34 0.6515453513308944 +35 0.6530749337706573 +36 0.652652327488331 +37 0.6532294689037467 +38 0.6523590261132837 +39 0.6523905638955468 +40 0.6523779487826417 +41 0.6531632395609941 +42 0.6514192002018419 +43 0.6526712501576889 +44 0.6532736217989151 +45 0.6522644127664943 +46 0.6517440393591523 +47 0.6535732307304151 +48 0.6522265674277785 +49 0.6521035700769522 +50 0.6520278793995207 +51 0.6525104074681468 +52 0.6517471931373786 +53 0.6533272360287624 +54 0.651662041125268 +55 0.6538034565409361 +56 0.6516525797905891 +57 0.6533997729279677 +58 0.6521004162987258 +59 0.6530560111012994 +60 0.6524788696858836 +61 0.6513182792985998 +62 0.6525167150245995 +63 0.6527059417181784 +64 0.6519963416172575 +65 0.6534660022707203 +66 0.6524883310205626 +67 0.6523306421092468 +68 0.6528163239560995 +69 0.6541377570329254 +70 0.6520941087422732 +71 0.6513088179639208 +72 0.6533398511416677 +73 0.6508609814557841 +74 0.6542039863756781 +75 0.6522707203229469 +76 0.6524631007947521 +77 0.6523369496656996 +78 0.6527974012867415 +79 0.6517345780244733 +80 0.6526870190488205 +81 0.6514034313107102 +82 0.6526365585971995 +83 0.6521981834237417 +84 0.6526397123754257 +85 0.6524504856818468 +86 0.6531474706698625 +87 0.6518891131575627 +88 0.6539516841175729 +89 0.6514948908792734 +90 0.6527090954964047 diff --git a/scenario2_random_immunization.dat b/scenario2_random_immunization.dat new file mode 100644 index 0000000000000000000000000000000000000000..09536c7edf7d981df7de3cafd1e4d0b9124680dc --- /dev/null +++ b/scenario2_random_immunization.dat @@ -0,0 +1,90 @@ +1 5.2046737970697684E-6 +2 1.0409347594139537E-5 +3 1.0409347594139538E-4 +4 0.0011190048663700003 +5 0.006453795508366513 +6 0.041772711895281964 +7 0.1875660342988003 +8 0.38429229448044344 +9 0.46847789314804694 +10 0.48930699768392016 +11 0.49389231529913863 +12 0.4978374580373175 +13 0.4966872251281651 +14 0.49830067400525674 +15 0.4966247690426003 +16 0.49951336299997395 +17 0.49857131704270435 +18 0.49627605589819657 +19 0.4984047674811981 +20 0.4988888021443256 +21 0.49647383350248525 +22 0.497951960860853 +23 0.4973742420693783 +24 0.4963957633955292 +25 0.49816535248653293 +26 0.49754079163088455 +27 0.4984412001977776 +28 0.49643740078590576 +29 0.4972128971816691 +30 0.498321492700445 +31 0.4969422541442215 +32 0.4973898560907695 +33 0.49795716553465014 +34 0.49727014859343693 +35 0.4967340671923387 +36 0.49913862648658497 +37 0.4987586852993989 +38 0.4960626642725167 +39 0.49918546855075857 +40 0.4975303822832904 +41 0.49793634683946186 +42 0.4981497384651417 +43 0.4960314362297343 +44 0.4973013766362193 +45 0.4985504983475161 +46 0.4968225466468889 +47 0.49876388997319593 +48 0.4981341244437505 +49 0.4978062299945351 +50 0.49730658131001637 +51 0.49907096572722304 +52 0.4978530720587087 +53 0.4983423113956333 +54 0.4965987456736149 +55 0.4991646498555703 +56 0.498920030187108 +57 0.49608868764150205 +58 0.5000286257058839 +59 0.4974210841335519 +60 0.49747833554531967 +61 0.4986650011710516 +62 0.4974731308715226 +63 0.49754079163088455 +64 0.4988679834491373 +65 0.49550576417623027 +66 0.49849845160954537 +67 0.49821219455070653 +68 0.499143831160382 +69 0.4962812605719937 +70 0.4983527207432274 +71 0.4967392718661358 +72 0.49860774975928385 +73 0.498769094646993 +74 0.49736903739558125 +75 0.4993988601764384 +76 0.49767611314960836 +77 0.4969682775132069 +78 0.49808728237957683 +79 0.49693704947042444 +80 0.49826424128867725 +81 0.4977906159731439 +82 0.49757201967366693 +83 0.4972649439196398 +84 0.499143831160382 +85 0.49679131860410647 +86 0.49925833398391756 +87 0.49672886251854165 +88 0.4976552944544201 +89 0.49705675696775703 +90 0.49838394878600983 diff --git a/scenario3_selective_immunization.dat b/scenario3_selective_immunization.dat new file mode 100644 index 0000000000000000000000000000000000000000..df63900adb654bc4f463044d214cdbdc23ce30c2 --- /dev/null +++ b/scenario3_selective_immunization.dat @@ -0,0 +1,90 @@ +1 0.0 +2 0.0 +3 0.0 +4 0.0 +5 0.0 +6 0.0 +7 0.0 +8 0.0 +9 0.0 +10 0.0 +11 0.0 +12 0.0 +13 0.0 +14 0.0 +15 0.0 +16 0.0 +17 0.0 +18 0.0 +19 0.0 +20 0.0 +21 0.0 +22 0.0 +23 0.0 +24 0.0 +25 0.0 +26 0.0 +27 0.0 +28 0.0 +29 0.0 +30 0.0 +31 0.0 +32 0.0 +33 0.0 +34 0.0 +35 0.0 +36 0.0 +37 0.0 +38 0.0 +39 0.0 +40 0.0 +41 0.0 +42 0.0 +43 0.0 +44 0.0 +45 0.0 +46 0.0 +47 0.0 +48 0.0 +49 0.0 +50 0.0 +51 0.0 +52 0.0 +53 0.0 +54 0.0 +55 0.0 +56 0.0 +57 0.0 +58 0.0 +59 0.0 +60 0.0 +61 0.0 +62 0.0 +63 0.0 +64 0.0 +65 0.0 +66 0.0 +67 0.0 +68 0.0 +69 0.0 +70 0.0 +71 0.0 +72 0.0 +73 0.0 +74 0.0 +75 0.0 +76 0.0 +77 0.0 +78 0.0 +79 0.0 +80 0.0 +81 0.0 +82 0.0 +83 0.0 +84 0.0 +85 0.0 +86 0.0 +87 0.0 +88 0.0 +89 0.0 +90 0.0 diff --git a/src/main/java/org/example/DBLPNetworkAnalysis.java b/src/main/java/org/example/DBLPNetworkAnalysis.java index 83a63230a732cff61025ccaaa966fca73b143143..4ae5db6f22e151195427eaad61b07efc814a824b 100644 --- a/src/main/java/org/example/DBLPNetworkAnalysis.java +++ b/src/main/java/org/example/DBLPNetworkAnalysis.java @@ -1,30 +1,34 @@ package org.example; import org.graphstream.algorithm.Toolkit; +import org.graphstream.algorithm.generator.Generator; +import org.graphstream.algorithm.generator.RandomGenerator; import org.graphstream.graph.*; import org.graphstream.graph.implementations.*; import org.graphstream.stream.file.FileSourceEdge; import org.graphstream.algorithm.generator.BarabasiAlbertGenerator; +import java.io.BufferedWriter; import java.io.FileWriter; +import java.io.IOException; +import java.io.PrintWriter; import java.util.*; + public class DBLPNetworkAnalysis { public static void main(String[] args) throws Exception { String filePath = "C:/Users/celia/IdeaProjects/TP_RI/com-dblp.ungraph.txt/com-dblp.ungraph.txt"; // Chemin du fichier d'entrée Graph graph = new SingleGraph("DBLP Collaboration Network"); - // --- Chargement des données --- FileSourceEdge fileSource = new FileSourceEdge(); fileSource.addSink(graph); - try { fileSource.readAll(filePath); } finally { fileSource.removeSink(graph); } - // --- Mesures de base --- + int nodeCount = graph.getNodeCount(); int edgeCount = graph.getEdgeCount(); double averageDegree = Toolkit.averageDegree(graph); @@ -33,223 +37,223 @@ public class DBLPNetworkAnalysis { boolean isConnected = Toolkit.isConnected(graph); double minAverageDegreeForConnectivity = Math.log(nodeCount); - // --- Calcul de la distribution des degrés --- - calculateDegreeDistribution(graph, "degree_distribution.txt"); - - // --- Distance moyenne et distribution des distances --- - double averageDistance = estimateAverageDistance(graph, 1000); - exportDistanceDistribution(graph, "distance_distribution.txt", 1000); - - // --- Affichage des résultats --- - System.out.println("Nombre de noeuds : " + nodeCount); - System.out.println("Nombre de liens : " + edgeCount); - System.out.println("Degré moyen : " + averageDegree); - System.out.println("Coefficient de clustering (réel) : " + clusteringCoefficient); - System.out.println("Coefficient de clustering (aléatoire) : " + randomClusteringCoefficient); - System.out.println("Le réseau est-il connexe ? : " + (isConnected ? "Oui" : "Non")); - System.out.println("Degré moyen minimal pour qu'un graphe aléatoire soit connexe : " + minAverageDegreeForConnectivity); - System.out.println("Distance moyenne estimée : " + averageDistance); - - // --- Génération et comparaison des réseaux aléatoires et Barabasi-Albert --- - compareWithGeneratedNetworks(nodeCount, edgeCount, averageDegree); - - // --- Génération d'un réseau selon la méthode de copie --- - Graph copyModelGraph = generateCopyModelGraph(nodeCount, averageDegree, 0.1); - System.out.println("\nRéseau généré avec la méthode de copie :"); - printGraphMeasures(copyModelGraph); - } - - // --- Calcul de la distribution des degrés --- - public static void calculateDegreeDistribution(Graph graph, String outputFile) throws Exception { - Map degreeCounts = new HashMap<>(); - - for (Node node : graph) { - int degree = node.getDegree(); - degreeCounts.put(degree, degreeCounts.getOrDefault(degree, 0) + 1); - } - - int totalNodes = graph.getNodeCount(); - - try (FileWriter writer = new FileWriter(outputFile)) { - writer.write("Degree\tProbability\n"); - for (Map.Entry entry : degreeCounts.entrySet()) { - double probability = (double) entry.getValue() / totalNodes; - writer.write(entry.getKey() + "\t" + probability + "\n"); - } - } + // Estimation de la distance moyenne par échantillonnage - System.out.println("Distribution des degrés exportée dans : " + outputFile); - } - - // --- Estimation de la distance moyenne --- - public static double estimateAverageDistance(Graph graph, int sampleSize) { + int sampleSize = 1000; List nodes = new ArrayList<>(); graph.nodes().forEach(nodes::add); + Random random = new Random(); double totalDistance = 0; - int count = 0; + int pairCount = 0; + Map distanceDistribution = new HashMap<>(); // Pour stocker les distances - // Échantillonner au maximum 1000 nœuds ou la taille totale du graphe - int actualSampleSize = Math.min(sampleSize, nodes.size()); + for (int i = 0; i < sampleSize; i++) { + Node startNode = nodes.get(random.nextInt(nodes.size())); - for (int i = 0; i < actualSampleSize; i++) { - Node start = nodes.get(random.nextInt(nodes.size())); - Map distances = bfsDistances(graph, start, 50); // Limite de profondeur - for (int distance : distances.values()) { - totalDistance += distance; - count++; - } - } + // BFS à partir du nœud de départ + BreadthFirstIterator bfs = new BreadthFirstIterator(startNode, true); + Map distances = new HashMap<>(); - return totalDistance / count; - } - - // --- Exportation de la distribution des distances --- - public static void exportDistanceDistribution(Graph graph, String outputFile, int sampleSize) throws Exception { - Map distanceCounts = new HashMap<>(); - List nodes = new ArrayList<>(); - graph.nodes().forEach(nodes::add); - Random random = new Random(); + while (bfs.hasNext()) { + Node node = bfs.next(); + int depth = bfs.getDepthOf(node); + distances.put(node, depth); - // Échantillonner au maximum 1000 nœuds ou la taille totale du graphe - int actualSampleSize = Math.min(sampleSize, nodes.size()); - - for (int i = 0; i < actualSampleSize; i++) { - Node start = nodes.get(random.nextInt(nodes.size())); - Map distances = bfsDistances(graph, start, 100); + // Enregistrer la distribution des distances + if (depth > 0) { + distanceDistribution.put(depth, distanceDistribution.getOrDefault(depth, 0) + 1); + } + } for (int distance : distances.values()) { - distanceCounts.put(distance, distanceCounts.getOrDefault(distance, 0) + 1); + if (distance > 0) { + totalDistance += distance; + pairCount++; + } } } - try (FileWriter writer = new FileWriter(outputFile)) { - writer.write("Distance\tFrequency\n"); + // Calculer la distance moyenne dans un réseau aléatoire + + double degreeAverage = Toolkit.averageDegree(graph); + double NetworkDistance = Math.log(graph.getNodeCount()) / Math.log(degreeAverage); + System.out.println("Distance moyenne dans notre réseau : " + NetworkDistance); - for (Map.Entry entry : distanceCounts.entrySet()) { - writer.write(entry.getKey() + "\t" + entry.getValue() + "\n"); + // Sauvegarder la distribution des distances dans un fichier + try (PrintWriter writer = new PrintWriter(new FileWriter("distance_distribution.dat"))) { + for (Map.Entry entry : distanceDistribution.entrySet()) { + writer.printf(Locale.US, "%d %f%n", entry.getKey(), + (double) entry.getValue() / pairCount); } + System.out.println("Distribution des distances sauvegardée dans 'distance_distribution.dat'."); + } catch (IOException e) { + e.printStackTrace(); } - System.out.println("Distribution des distances exportée dans : " + outputFile); - } - // --- BFS pour calculer les distances --- - public static Map bfsDistances(Graph graph, Node start, int maxDepth) { - Map distances = new HashMap<>(); - Queue queue = new LinkedList<>(); - distances.put(start, 0); - queue.add(start); + //Calcul de la distribution des degrés + calculateDegreeDistribution(graph, "degree_distribution.txt"); - while (!queue.isEmpty()) { - Node current = queue.poll(); - int currentDistance = distances.get(current); + // Résultats des mesures principales + System.out.println("Nombre de noeuds : " + nodeCount); + System.out.println("Nombre de liens : " + edgeCount); + System.out.println("Degré moyen : " + averageDegree); + System.out.println("Coefficient de clustering (réel) : " + clusteringCoefficient); + System.out.println("Coefficient de clustering (aléatoire) : " + randomClusteringCoefficient); + System.out.println("Le réseau est-il connexe ? : " + (isConnected ? "Oui" : "Non")); + System.out.println("Degré moyen minimal pour qu'un graphe aléatoire soit connexe : " + minAverageDegreeForConnectivity); - if (currentDistance >= maxDepth) continue; + // Génération et comparaison des réseaux aléatoires et Barabasi-Albert + compareWithGeneratedNetworks(graph); + + System.out.println("Analyse du réseau généré par la méthode de copie :"); + Graph grapheCopie = genererGrapheCopie(nodeCount, 0.5); + printGraphMeasures(grapheCopie); + } - current.edges().forEach(edge -> { - Node neighbor = edge.getOpposite(current); - if (!distances.containsKey(neighbor)) { - distances.put(neighbor, currentDistance + 1); - queue.add(neighbor); + // --- Calcul de la distribution des degrés --- + public static void calculateDegreeDistribution(Graph graph, String outputFile) throws IOException { + int[] distribution = Toolkit.degreeDistribution(graph); + try (BufferedWriter writer = new BufferedWriter(new FileWriter(outputFile))) { + writer.write("# Degree\tProbability\n"); + for (int k = 0; k < distribution.length; k++) { + if (distribution[k] != 0) { + double probability = (double) distribution[k] / graph.getNodeCount(); + writer.write(k + "\t" + probability + "\n"); } - }); + } } - - return distances; + System.out.println("Distribution des degrés écrite dans : " + outputFile); } // --- Comparaison avec des réseaux générés --- - public static void compareWithGeneratedNetworks(int nodeCount, int edgeCount, double averageDegree) { - Graph randomGraph = createRandomGraph(nodeCount, edgeCount); - - // Générer un graphe Barabasi-Albert avec le même degré moyen - int edgesPerNode = (int) Math.round(averageDegree / 2); - Graph baGraph = generateBarabasiAlbertGraph(nodeCount, edgesPerNode); + public static void compareWithGeneratedNetworks(Graph initialGraph) throws Exception { - System.out.println("\nR\u00e9seau al\u00e9atoire :"); + // --- Générer un graphe aléatoire --- + System.out.println("\nGénération du réseau aléatoire..."); + Graph randomGraph = createRandomGraph(initialGraph); + System.out.println("Réseau aléatoire :"); printGraphMeasures(randomGraph); + calculateDegreeDistribution(randomGraph, "random_degree_distribution.txt"); + double degreeAverage = Toolkit.averageDegree(randomGraph); + double NetworkDistance = Math.log(randomGraph.getNodeCount()) / Math.log(degreeAverage); + System.out.println("Distance moyenne du réseau Aléatoire : " + NetworkDistance); - System.out.println("\nR\u00e9seau Barabasi-Albert :"); + + // --- Générer un graphe Barabási-Albert --- + System.out.println("\nGénération du réseau Barabási-Albert..."); + Graph baGraph = generateBarabasiAlbertGraph(initialGraph); + System.out.println("Réseau Barabási-Albert :"); printGraphMeasures(baGraph); - } + calculateDegreeDistribution(baGraph, "barabasi_degree_distribution.txt"); - // --- Génération d'un réseau aléatoire --- - public static Graph createRandomGraph(int nodeCount, int edgeCount) { - Graph randomGraph = new SingleGraph("Random Network"); - Random random = new Random(); - for (int i = 0; i < nodeCount; i++) { - randomGraph.addNode(String.valueOf(i)); + // --- Sauvegarder les résultats --- + try (FileWriter writer = new FileWriter("comparison_results.txt")) { + writer.write("Comparaison des réseaux générés :\n"); + + writer.write("\nRéseau aléatoire :\n"); + writer.write(captureGraphMeasures(randomGraph)); + + writer.write("\nRéseau Barabási-Albert :\n"); + writer.write(captureGraphMeasures(baGraph)); } + System.out.println("\nLes résultats de la comparaison ont été sauvegardés dans 'comparison_results.txt'."); + } - Set edges = new HashSet<>(); + // Méthode pour capturer les métriques d'un graphe + public static String captureGraphMeasures(Graph graph) { + return String.format("Nombre de noeuds : %d\nNombre de liens : %d\nDegré moyen : %.4f\nCoefficient de clustering : %.4f\n", + graph.getNodeCount(), + graph.getEdgeCount(), + Toolkit.averageDegree(graph), + Toolkit.averageClusteringCoefficient(graph)); + } - while (randomGraph.getEdgeCount() < edgeCount) { - int source = random.nextInt(nodeCount); - int target = random.nextInt(nodeCount); + // --- Génération d'un réseau aléatoire --- + public static Graph createRandomGraph(Graph initialGraph) { - if (source != target) { - String edge = source + "-" + target; - String reverseEdge = target + "-" + source; + double averageDegree = Toolkit.averageDegree(initialGraph); - if (!edges.contains(edge) && !edges.contains(reverseEdge)) { - randomGraph.addEdge(edge, String.valueOf(source), String.valueOf(target)); - edges.add(edge); - } - } + Generator generator = new RandomGenerator(averageDegree, false); + Graph graphAlea = new SingleGraph("graphe aléatoire"); + int N = 317080; + + // graphe aléatoire générer de taille N + generator.addSink(graphAlea); + generator.begin(); + while (graphAlea.getNodeCount() < N) { + generator.nextEvents(); + } + generator.end(); + if (graphAlea.getNodeCount() == N) { + System.out.println("Graph aléatoire générer !"); } - return randomGraph; + + return graphAlea; } + // --- Génération d'un réseau Barabasi-Albert --- - public static Graph generateBarabasiAlbertGraph(int nodeCount, double averageDegree) { - int edgesPerNode = (int) Math.round(averageDegree *2); // Calculez m correctement - Graph graph = new SingleGraph("Barabasi-Albert Network"); - BarabasiAlbertGenerator generator = new BarabasiAlbertGenerator(edgesPerNode); + public static Graph generateBarabasiAlbertGraph(Graph initialGraph) { + int nodeCount = initialGraph.getNodeCount(); + double averageDegree = Toolkit.averageDegree(initialGraph); - generator.addSink(graph); + Graph barabasiGraph = new SingleGraph("Barabasi-Albert Network"); + BarabasiAlbertGenerator generator = new BarabasiAlbertGenerator((int) averageDegree); + generator.addSink(barabasiGraph); generator.begin(); - - while (graph.getNodeCount() < nodeCount) { + while (barabasiGraph.getNodeCount() < nodeCount) { generator.nextEvents(); } - generator.end(); - return graph; + return barabasiGraph; } + public static Graph genererGrapheCopie(int nombreNoeuds, double probabilitéCopie) { + Graph grapheCopie = new SingleGraph("GrapheCopie"); + Random aleatoire = new Random(); - // --- Génération d'un réseau selon la méthode de copie --- - public static Graph generateCopyModelGraph(int nodeCount, double averageDegree, double probability) { - Graph copyGraph = new SingleGraph("Copy Model Network"); - Random random = new Random(); + // Ajouter un premier nœud pour démarrer le réseau + grapheCopie.addNode("0"); + + for (int i = 1; i < nombreNoeuds; i++) { + Node nouveauNoeud = grapheCopie.addNode(String.valueOf(i)); - copyGraph.addNode("0"); + // Choisir un nœud aléatoire existant + Node noeudCible = grapheCopie.getNode(aleatoire.nextInt(grapheCopie.getNodeCount())); - for (int i = 1; i < nodeCount; i++) { - copyGraph.addNode(String.valueOf(i)); - Node targetNode = copyGraph.getNode(String.valueOf(random.nextInt(i))); + // Parcourir les voisins de noeudCible + noeudCible.edges().forEach(edge -> { + if (edge != null) { // Vérifier que l'arête n'est pas null + Node voisin = edge.getOpposite(noeudCible); - int finalI = i; - targetNode.neighborNodes().forEach(neighbor -> { - if (random.nextDouble() < probability) { - copyGraph.addEdge(finalI + "-" + neighbor.getId(), String.valueOf(finalI), neighbor.getId()); + // Connecter au voisin avec probabilité p + String edgeIdVoisin = nouveauNoeud.getId() + "-" + voisin.getId(); + if (aleatoire.nextDouble() < probabilitéCopie && grapheCopie.getEdge(edgeIdVoisin) == null) { + grapheCopie.addEdge(edgeIdVoisin, nouveauNoeud, voisin); + } } }); - copyGraph.addEdge(i + "-" + targetNode.getId(), String.valueOf(i), targetNode.getId()); + // Connecter le nouveau nœud au nœud cible + String edgeIdCible = nouveauNoeud.getId() + "-" + noeudCible.getId(); + if (grapheCopie.getEdge(edgeIdCible) == null) { + grapheCopie.addEdge(edgeIdCible, nouveauNoeud, noeudCible); + } } - return copyGraph; + return grapheCopie; } + + // --- Affichage des mesures d'un graphe --- public static void printGraphMeasures(Graph graph) { - System.out.println("Nombre de n\u0153uds : " + graph.getNodeCount()); + System.out.println("Nombre de nœuds : " + graph.getNodeCount()); System.out.println("Nombre de liens : " + graph.getEdgeCount()); - System.out.println("Degr\u00e9 moyen : " + Toolkit.averageDegree(graph)); + System.out.println("Degré moyen : " + Toolkit.averageDegree(graph)); System.out.println("Coefficient de clustering : " + Toolkit.averageClusteringCoefficient(graph)); - System.out.println("Distance moyenne estim\u00e9e : " + estimateAverageDistance(graph, 100)); } } \ No newline at end of file diff --git a/src/main/java/org/example/Propagation.java b/src/main/java/org/example/Propagation.java new file mode 100644 index 0000000000000000000000000000000000000000..3a9c60cedf8faab615e80bf9e26c86a758c50066 --- /dev/null +++ b/src/main/java/org/example/Propagation.java @@ -0,0 +1,362 @@ +package org.example; + +import org.graphstream.graph.Graph; +import org.graphstream.graph.Node; +import org.graphstream.graph.implementations.SingleGraph; +import org.graphstream.stream.file.FileSourceEdge; +import org.graphstream.algorithm.Toolkit; +import java.io.BufferedWriter; +import java.io.FileWriter; +import java.io.IOException; + +import java.util.*; + +public class Propagation { + + public static void main(String[] args) throws Exception { + String filePath = "C:/Users/celia/IdeaProjects/TP_RI/com-dblp.ungraph.txt/com-dblp.ungraph.txt"; + Graph graph = new SingleGraph("DBLP Collaboration Network"); + + // --- Chargement des données --- + FileSourceEdge fileSource = new FileSourceEdge(); + fileSource.addSink(graph); + try { + fileSource.readAll(filePath); + } finally { + fileSource.removeSink(graph); + } +// Appliquer une immunisation aléatoire (immuniser 50 % des nœuds) + Set immune = new HashSet<>(); + Random random = new Random(); + int immuneCount = (int) (0.5 * graph.getNodeCount()); // Immuniser 50 % des nœuds + List nodes = new ArrayList<>(graph.nodes().toList()); + Collections.shuffle(nodes, random); + for (int i = 0; i < immuneCount; i++) { + Node node = nodes.get(i); + node.setAttribute("immune", true); // Marquer comme immunisé + immune.add(node); + } + + // Groupes + Set group0 = new HashSet<>(); // Groupe 0 : 50 % des nœuds non immunisés + Set group1 = new HashSet<>(); // Groupe 1 : Un voisin immunisé de chaque nœud du Groupe 0 + + // Sélectionner 50 % des nœuds non immunisés pour le Groupe 0 + List nonImmuneNodes = new ArrayList<>(); + for (Node node : graph) { + if (!immune.contains(node)) { // Nœuds non immunisés + nonImmuneNodes.add(node); + } + } + Collections.shuffle(nonImmuneNodes, random); // Mélanger les nœuds non immunisés + int targetCount = (int) (0.5 * nonImmuneNodes.size()); // 50 % des nœuds non immunisés + for (int i = 0; i < targetCount; i++) { + group0.add(nonImmuneNodes.get(i)); // Ajouter au groupe 0 + } + + // Pour chaque nœud du Groupe 0, ajouter un voisin immunisé au Groupe 1 + for (Node node : group0) { + List neighbors = node.neighborNodes().toList(); + for (Node neighbor : neighbors) { + if (immune.contains(neighbor)) { // Vérifier si le voisin est immunisé + group1.add(neighbor); // Ajouter un seul voisin immunisé au groupe 1 + break; // Sortir de la boucle après avoir trouvé un voisin immunisé + } + } + } + + // Calcul du degré moyen pour le Groupe 0 (non immunisé) + double totalDegreeGroup0 = 0; + for (Node node : group0) { + totalDegreeGroup0 += node.getDegree(); + } + double averageDegreeGroup0 = group0.isEmpty() ? 0 : totalDegreeGroup0 / group0.size(); + System.out.printf("Degré moyen (Groupe 0 - Non immunisé) : %.9f%n", averageDegreeGroup0); + + // Calcul du degré moyen pour le Groupe 1 (voisins immunisés) + double totalDegreeGroup1 = 0; + for (Node node : group1) { + totalDegreeGroup1 += node.getDegree(); + } + double averageDegreeGroup1 = group1.isEmpty() ? 0 : totalDegreeGroup1 / group1.size(); + System.out.printf("Degré moyen (Groupe 1 - Voisins immunisés) : %.9f%n", averageDegreeGroup1); + + // --- Paramètres --- + int daysToSimulate = 90; // 3 mois + double infectionProbability = 1.0; // β = 1 + double recoveryProbability = 0.5; // μ = 0.5 + + // Tableau pour stocker les résultats des scénarios + double[][] results = new double[3][daysToSimulate]; + String[] fileNames = {"scenario1_no_control.dat", "scenario2_random_immunization.dat", "scenario3_selective_immunization.dat"}; + + // --- Scenarios --- + System.out.println("Scenario 1: No Control"); + results[0] = simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0, false); + + System.out.println("Scenario 2: Random Immunization"); + results[1] = simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0.5, true); + + System.out.println("Scenario 3: Selective Immunization"); + results[2] = simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0.5, false); + + // Sauvegarde des résultats dans des fichiers + saveResultsToFiles(results, fileNames); + + System.out.println("Les résultats ont été sauvegardés dans les fichiers pour Gnuplot."); + + // Calculer les degrés moyens des groupes 0 et 1 + + + + + + epidemicThresholdAnalysis(graph,infectionProbability,recoveryProbability); + + // Réseau modifié après immunisation aléatoire + System.out.println("Analyse après immunisation aléatoire :"); + Graph randomImmunizedGraph = cloneGraph(graph); + applyRandomImmunization(randomImmunizedGraph, 0.5); // 50% des nœuds immunisés + epidemicThresholdAnalysis(randomImmunizedGraph, infectionProbability, recoveryProbability); + + // Réseau modifié après immunisation sélective + System.out.println("Analyse après immunisation sélective :"); + Graph selectiveImmunizedGraph = cloneGraph(graph); + applySelectiveImmunization(selectiveImmunizedGraph, 0.5); // 50% des voisins des hubs immunisés + epidemicThresholdAnalysis(selectiveImmunizedGraph, infectionProbability, recoveryProbability); + + } + + private static Graph cloneGraph(Graph original) { + Graph clone = new SingleGraph("Clone"); + + // Ajouter tous les nœuds au clone + original.nodes().toList().forEach(node -> clone.addNode(node.getId())); + + // Ajouter toutes les arêtes au clone + original.edges().toList().forEach(edge -> { + String sourceId = edge.getSourceNode().getId(); + String targetId = edge.getTargetNode().getId(); + String edgeId = sourceId + "-" + targetId; + if (clone.getEdge(edgeId) == null) { + clone.addEdge(edgeId, sourceId, targetId); + } + }); + + return clone; + } + + private static void applyRandomImmunization(Graph graph, double fraction) { + Random random = new Random(); + int immunizedCount = (int) (fraction * graph.getNodeCount()); + for (int i = 0; i < immunizedCount; i++) { + Node node = graph.getNode(random.nextInt(graph.getNodeCount())); + if (node != null) { + graph.removeNode(node); + } + } + } + private static void applySelectiveImmunization(Graph graph, double fraction) { + Random random = new Random(); + + // Créer une liste des nœuds pour éviter les modifications concurrentes du graphe + var nodes = graph.nodes().toList(); + + for (Node node : nodes) { + if (node != null && random.nextDouble() < fraction) { + // Parcourir les voisins et les supprimer + var neighbors = node.neighborNodes().toList(); + for (Node neighbor : neighbors) { + if (graph.getNode(neighbor.getId()) != null) { // Vérifier que le voisin existe toujours + graph.removeNode(neighbor.getId()); + } + } + } + } + } + + + + private static void epidemicThresholdAnalysis(Graph graph, double infectionRate, double recoveryRate) { + double avgDegree = Toolkit.averageDegree(graph); // Utilisation de Toolkit pour le degré moyen + double avgDegreeSquared = calculateSquaredAverageDegree(graph); // Calcul direct du carré moyen des degrés + + // Calcul des seuils + double tau = infectionRate / recoveryRate; // Taux de propagation + double cReal = avgDegree / avgDegreeSquared; // Seuil épidémique réel + double cTheoretical = 1.0 / (avgDegree + 1); // Seuil théorique pour un réseau aléatoire avec normalisation + + // Affichage des résultats + System.out.println("Taux de propagation (τ) : " + tau); + System.out.println("Seuil épidémique réel (c_réel) : " + cReal); + System.out.println("Seuil épidémique théorique (c_théorique) : " + cTheoretical); + + // Prédiction dans le réseau réel + if (tau > cReal) { + System.out.println("La maladie persiste dans le réseau réel (τ > c_réel).\n"); + } else { + System.out.println("La maladie disparaît dans le réseau réel (τ < c_réel).\n"); + } + + // Comparaison avec le réseau aléatoire + if (cReal < cTheoretical) { + System.out.println("Le réseau réel est plus vulnérable que le réseau aléatoire (c_réel < c_théorique).\n"); + } else { + System.out.println("Le réseau réel est plus résistant que le réseau aléatoire (c_réel >= c_théorique).\n"); + } + } + + + + + private static double calculateSquaredAverageDegree(Graph graph) { + double totalDegreeSquared = 0; + for (Node node : graph) { + totalDegreeSquared += Math.pow(node.getDegree(), 2); // Somme des carrés des degrés + } + return totalDegreeSquared / graph.getNodeCount(); // Moyenne des carrés des degrés + } + + + + private static void saveResultsToFiles(double[][] results, String[] fileNames) { + for (int i = 0; i < results.length; i++) { + try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileNames[i]))) { + for (int day = 0; day < results[i].length; day++) { + writer.write((day + 1) + "\t" + results[i][day]); + writer.newLine(); + } + } catch (IOException e) { + System.err.println("Erreur lors de l'écriture dans le fichier : " + fileNames[i]); + e.printStackTrace(); + } + } + } + + + + + + private static double[] simulateAndCaptureResults(Graph graph, double infectionRate, double recoveryRate, int days, double immunizationFraction, boolean randomImmunization) { + double[] infectedFractions = new double[days]; + Random random = new Random(); + + // initialisation + for (Node node : graph) { + node.setAttribute("state", "susceptible"); + node.removeAttribute("immune"); + } + + // Immunization + if (immunizationFraction > 0) { + int immunizedCount = (int) (immunizationFraction * graph.getNodeCount()); + if (randomImmunization) { + // Immunisation aléatoire : immuniser des nœuds directement + for (int i = 0; i < immunizedCount; i++) { + Node node = graph.getNode(random.nextInt(graph.getNodeCount())); + node.setAttribute("immune", true); + } + } else { + // Immunisation sélective : immuniser un voisin pour 50% des nœuds existants + List nodes = new ArrayList<>( graph.nodes().toList()); + + // Calculer le nombre de nœuds à immuniser (50% des nœuds existants) + int nodesToImmunize = (int) (immunizationFraction * nodes.size()); + + // Mélanger les nœuds pour garantir une sélection aléatoire + Collections.shuffle(nodes, random); + + // Sélectionner les premiers `nodesToImmunize` nœuds et immuniser un voisin pour chacun + for (int i = 0; i < nodesToImmunize; i++) { + Node node = nodes.get(i); + + // Vérifier que le nœud a des voisins + if (node.getDegree() > 0) { + // Prendre un voisin aléatoire + List neighbors = node.neighborNodes().toList(); + Node neighbor = neighbors.get(random.nextInt(neighbors.size())); + + // Immuniser ce voisin + neighbor.setAttribute("immune", true); + } + } + + } + + } + // Infect patient zero + Node patientZero = graph.getNode(new Random().nextInt(graph.getNodeCount())); + patientZero.setAttribute("state", "infected"); + + // Simulation + for (int day = 0; day < days; day++) { + int infectedCount = 0; + int totalNonImmune = 0; + + for (Node node : graph) { + if (!node.hasAttribute("immune")) { + totalNonImmune++; + if (node.getAttribute("state").equals("infected")) { + infectedCount++; + for (Node neighbor : node.neighborNodes().toList()) { + if (!neighbor.hasAttribute("immune") && neighbor.getAttribute("state").equals("susceptible") && random.nextDouble() < infectionRate) { + neighbor.setAttribute("nextState", "infected"); + } + } + if (random.nextDouble() < recoveryRate) { + node.setAttribute("nextState", "susceptible"); + } + } + } + } + // mise à jour de l'état des noeuds + for (Node node : graph) { + if (node.hasAttribute("nextState")) { + node.setAttribute("state", node.getAttribute("nextState")); + node.removeAttribute("nextState"); + } + } + + infectedFractions[day] = (double) infectedCount / totalNonImmune; + } + + return infectedFractions; + } + + public static void calculateAverageDegrees(Graph graph, Set immune) { + // Groupes 0 (non immunisés) et 1 (immunisés) + Set group0 = new HashSet<>(); + Set group1 = immune; // Groupe 1 est directement le set 'immune' (les nœuds immunisés) + + // Ajouter 50 % des nœuds au groupe 0 + Random random = new Random(); + List nodes = new ArrayList<>(); + for (Node node : graph) { + nodes.add(node); + } + Collections.shuffle(nodes); // Mélanger les nœuds pour une sélection aléatoire + + int targetConvincers = graph.getNodeCount() / 2; // 50 % des nœuds + for (int i = 0; i < targetConvincers; i++) { + group0.add(nodes.get(i)); // Ajouter au groupe 0 + } + + // Calcul du degré moyen pour le groupe 0 (non immunisé) + double totalDegreeGroup0 = 0; + for (Node node : group0) { + totalDegreeGroup0 += node.getDegree(); + } + double averageDegreeGroup0 = group0.isEmpty() ? 0 : totalDegreeGroup0 / group0.size(); + System.out.println("Degré moyen du groupe 0 (non immunisé) : " + averageDegreeGroup0); + + // Calcul du degré moyen pour le groupe 1 (immunisé) + double totalDegreeGroup1 = 0; + for (Node node : group1) { + totalDegreeGroup1 += node.getDegree(); + } + double averageDegreeGroup1 = group1.isEmpty() ? 0 : totalDegreeGroup1 / group1.size(); + System.out.println("Degré moyen du groupe 1 (immunisé) : " + averageDegreeGroup1); + } + + +}