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.Random; 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); } // --- Paramètres --- int daysToSimulate = 90; // 3 months 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 calculateAverageDegreeSelectiveImmunization(graph); 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(); // Reset states 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 for (Node node : graph) { if (random.nextDouble() < immunizationFraction && node.getDegree() > 0) { Node neighbor = node.neighborNodes().toList().get(0); // Prendre un 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"); } } } } for (Node node : graph) { if (node.hasAttribute("nextState")) { node.setAttribute("state", node.getAttribute("nextState")); node.removeAttribute("nextState"); } } infectedFractions[day] = (double) infectedCount / totalNonImmune; } return infectedFractions; } private static void calculateAverageDegreeSelectiveImmunization(Graph graph) { double totalDegreeGroup0 = 0; // Somme des degrés des nœuds du groupe 0 double totalDegreeGroup1 = 0; // Somme des degrés des nœuds du groupe 1 int countGroup0 = 0; // Nombre de nœuds dans le groupe 0 int countGroup1 = 0; // Nombre de nœuds dans le groupe 1 // Parcourir tous les nœuds pour identifier les groupes for (Node node : graph) { if (node.hasAttribute("selected")) { // Groupe 0 : nœuds choisis aléatoirement totalDegreeGroup0 += node.getDegree(); countGroup0++; // Groupe 1 : voisins immunisés de ces nœuds for (Node neighbor : node.neighborNodes().toList()) { if (neighbor.hasAttribute("immune")) { totalDegreeGroup1 += neighbor.getDegree(); countGroup1++; } } } } // Calcul des degrés moyens double avgDegreeGroup0 = countGroup0 > 0 ? totalDegreeGroup0 / countGroup0 : 0; double avgDegreeGroup1 = countGroup1 > 0 ? totalDegreeGroup1 / countGroup1 : 0; // Afficher les résultats System.out.printf("Degré moyen (Groupe 0 - Nœuds sélectionnés aléatoirement) : %.9f%n", avgDegreeGroup0); System.out.printf("Degré moyen (Groupe 1 - Voisins immunisés) : %.9f%n", avgDegreeGroup1); } }