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é } } } // --- Paramètres --- int daysToSimulate = 90; // 3 mois double infectionProbability = 1.0; // β = 1 double recoveryProbability = 0.5; // μ = 0.5 // Nombre d'itérations pour chaque scénario int iterations = 10; // 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"}; // --- Scénarios avec itérations --- for (int scenario = 0; scenario < 3; scenario++) { double[] averageFractions = new double[daysToSimulate]; Arrays.fill(averageFractions, 0); // Initialiser à zéro pour chaque scénario for (int iteration = 0; iteration < iterations; iteration++) { // Cloner le graphe pour garantir une nouvelle simulation à chaque itération Graph graphClone = cloneGraph(graph); // Définir les paramètres spécifiques au scénario double immunizationFraction = 0; boolean randomImmunization = false; if (scenario == 1) { // Immunisation aléatoire immunizationFraction = 0.5; randomImmunization = true; } else if (scenario == 2) { // Immunisation sélective immunizationFraction = 0.5; randomImmunization = false; } // Exécuter la simulation et capturer les résultats double[] fractions = simulateAndCaptureResults(graphClone, infectionProbability, recoveryProbability, daysToSimulate, immunizationFraction, randomImmunization); // Ajouter les résultats de cette itération à la moyenne for (int day = 0; day < daysToSimulate; day++) { averageFractions[day] += fractions[day]; } } // Diviser par le nombre d'itérations pour obtenir la moyenne for (int day = 0; day < daysToSimulate; day++) { averageFractions[day] /= iterations; } // Stocker les résultats du scénario results[scenario] = averageFractions; // Enregistrer les résultats dans un fichier writeResultsToFile(fileNames[scenario], averageFractions); } epidemicThresholdAnalysis(graph,infectionProbability,recoveryProbability); // 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); // 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); Graph barabasiGraph = DBLPNetworkAnalysis.generateBarabasiAlbertGraph(graph); // Exemple : 3 connexions par nœud System.out.println("Simulation sur réseau Barabási-Albert :"); runSimulations(barabasiGraph); } // --- Méthode pour écrire les résultats dans un fichier --- private static void writeResultsToFile(String fileName, double[] data) { try (BufferedWriter writer = new BufferedWriter(new FileWriter(fileName))) { for (int day = 0; day < data.length; day++) { writer.write(day + " " + data[day]); writer.newLine(); } } catch (IOException e) { System.err.println("Erreur lors de l'écriture du fichier : " + e.getMessage()); } } private static void runSimulations(Graph graph) { int daysToSimulate = 90; // 3 mois double infectionProbability = 1.0; // β = 1 double recoveryProbability = 0.5; // μ = 0.5 // Scénario 1 : Aucune immunisation System.out.println("Scénario 1 : Aucune immunisation"); simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0, false); // Scénario 2 : Immunisation aléatoire System.out.println("Scénario 2 : Immunisation aléatoire"); applyRandomImmunization(graph, 0.5); // Immunisation aléatoire de 50 % simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0, true); // Scénario 3 : Immunisation sélective System.out.println("Scénario 3 : Immunisation sélective"); applySelectiveImmunization(graph, 0.5); // Immunisation sélective de 50 % simulateAndCaptureResults(graph, infectionProbability, recoveryProbability, daysToSimulate, 0, false); } 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 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); } 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 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) { // Récupérer tous les nœuds dans une liste List allNodes = new ArrayList<>(graph.nodes().toList()); // Mélanger la liste pour une sélection aléatoire unique Collections.shuffle(allNodes, random); // Immuniser les premiers `immunizedCount` nœuds for (int i = 0; i < immunizedCount; i++) { Node node = allNodes.get(i); if (node != null) { 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; } }