- Created summary.csv to store simulation results for various scenarios, protocols, and metrics. - Developed run.sh script to automate the simulation process, including dependency checks, simulation execution, and result analysis. - Ensured proper directory structure for results and reports. - Added error handling for Python and matplotlib dependencies.
239 lines
9.3 KiB
Python
239 lines
9.3 KiB
Python
"""
|
|
Analyseur et générateur de graphiques pour les résultats de simulation
|
|
"""
|
|
|
|
import json
|
|
import matplotlib.pyplot as plt
|
|
import matplotlib
|
|
matplotlib.use('Agg') # Backend sans affichage
|
|
|
|
|
|
class ResultsAnalyzer:
|
|
"""Analyse et visualise les résultats des simulations."""
|
|
|
|
def __init__(self, results_file):
|
|
"""
|
|
Charge les résultats depuis un fichier JSON.
|
|
|
|
Args:
|
|
results_file (str): Chemin vers le fichier JSON
|
|
"""
|
|
with open(results_file, 'r') as f:
|
|
self.results = json.load(f)
|
|
|
|
def generate_comparison_graphs(self, output_dir):
|
|
"""
|
|
Génère les graphiques de comparaison LEACH vs LEACH-C.
|
|
|
|
Args:
|
|
output_dir (str): Répertoire de sortie
|
|
"""
|
|
# 1. FDN Comparison
|
|
self._plot_fdn_comparison(output_dir)
|
|
|
|
# 2. FMR Comparison
|
|
self._plot_fmr_comparison(output_dir)
|
|
|
|
# 3. DLBI Comparison
|
|
self._plot_dlbi_comparison(output_dir)
|
|
|
|
# 4. RSPI Comparison
|
|
self._plot_rspi_comparison(output_dir)
|
|
|
|
# 5. Alive Nodes Over Rounds
|
|
self._plot_alive_nodes(output_dir)
|
|
|
|
def _plot_fdn_comparison(self, output_dir):
|
|
"""Graphique : FDN pour tous les scénarios."""
|
|
scenarios = list(self.results.keys())
|
|
leach_fdn = []
|
|
leachc_fdn = []
|
|
|
|
for scenario in scenarios:
|
|
leach_metrics = self.results[scenario]["LEACH"]["metrics"]
|
|
leachc_metrics = self.results[scenario]["LEACH-C"]["metrics"]
|
|
|
|
leach_fdn.append(leach_metrics.get("first_dead_node_round") or 0)
|
|
leachc_fdn.append(leachc_metrics.get("first_dead_node_round") or 0)
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 6))
|
|
x_pos = range(len(scenarios))
|
|
width = 0.35
|
|
|
|
ax.bar([i - width/2 for i in x_pos], leach_fdn, width, label='LEACH', color='#FF6B6B')
|
|
ax.bar([i + width/2 for i in x_pos], leachc_fdn, width, label='LEACH-C', color='#4ECDC4')
|
|
|
|
ax.set_xlabel('Scénario', fontsize=12)
|
|
ax.set_ylabel('Premier Nœud Mort (Round)', fontsize=12)
|
|
ax.set_title('Comparaison FDN (First Dead Node)', fontsize=14, fontweight='bold')
|
|
ax.set_xticks(x_pos)
|
|
ax.set_xticklabels(scenarios, rotation=45, ha='right')
|
|
ax.legend()
|
|
ax.grid(axis='y', alpha=0.3)
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(f"{output_dir}/01_FDN_Comparison.png", dpi=300)
|
|
plt.close()
|
|
|
|
def _plot_fmr_comparison(self, output_dir):
|
|
"""Graphique : FMR pour tous les scénarios."""
|
|
scenarios = list(self.results.keys())
|
|
leach_fmr = []
|
|
leachc_fmr = []
|
|
|
|
for scenario in scenarios:
|
|
leach_metrics = self.results[scenario]["LEACH"]["metrics"]
|
|
leachc_metrics = self.results[scenario]["LEACH-C"]["metrics"]
|
|
|
|
leach_fmr.append(leach_metrics.get("first_muted_round") or 9999)
|
|
leachc_fmr.append(leachc_metrics.get("first_muted_round") or 9999)
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 6))
|
|
x_pos = range(len(scenarios))
|
|
width = 0.35
|
|
|
|
ax.bar([i - width/2 for i in x_pos], leach_fmr, width, label='LEACH', color='#FF6B6B')
|
|
ax.bar([i + width/2 for i in x_pos], leachc_fmr, width, label='LEACH-C', color='#4ECDC4')
|
|
|
|
ax.set_xlabel('Scénario', fontsize=12)
|
|
ax.set_ylabel('Premier Round Muet', fontsize=12)
|
|
ax.set_title('Comparaison FMR (First Muted Round)', fontsize=14, fontweight='bold')
|
|
ax.set_xticks(x_pos)
|
|
ax.set_xticklabels(scenarios, rotation=45, ha='right')
|
|
ax.legend()
|
|
ax.grid(axis='y', alpha=0.3)
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(f"{output_dir}/02_FMR_Comparison.png", dpi=300)
|
|
plt.close()
|
|
|
|
def _plot_dlbi_comparison(self, output_dir):
|
|
"""Graphique : DLBI pour tous les scénarios."""
|
|
scenarios = list(self.results.keys())
|
|
leach_dlbi = []
|
|
leachc_dlbi = []
|
|
|
|
for scenario in scenarios:
|
|
leach_metrics = self.results[scenario]["LEACH"]["metrics"]
|
|
leachc_metrics = self.results[scenario]["LEACH-C"]["metrics"]
|
|
|
|
leach_dlbi.append(leach_metrics.get("dlbi", 0))
|
|
leachc_dlbi.append(leachc_metrics.get("dlbi", 0))
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 6))
|
|
x_pos = range(len(scenarios))
|
|
width = 0.35
|
|
|
|
ax.bar([i - width/2 for i in x_pos], leach_dlbi, width, label='LEACH', color='#FF6B6B')
|
|
ax.bar([i + width/2 for i in x_pos], leachc_dlbi, width, label='LEACH-C', color='#4ECDC4')
|
|
|
|
ax.set_xlabel('Scénario', fontsize=12)
|
|
ax.set_ylabel('DLBI (0 à 1)', fontsize=12)
|
|
ax.set_title('Comparaison DLBI (Dynamic Load Balancing Index)', fontsize=14, fontweight='bold')
|
|
ax.set_xticks(x_pos)
|
|
ax.set_xticklabels(scenarios, rotation=45, ha='right')
|
|
ax.set_ylim([0, 1.1])
|
|
ax.legend()
|
|
ax.grid(axis='y', alpha=0.3)
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(f"{output_dir}/03_DLBI_Comparison.png", dpi=300)
|
|
plt.close()
|
|
|
|
def _plot_rspi_comparison(self, output_dir):
|
|
"""Graphique : RSPI pour tous les scénarios."""
|
|
scenarios = list(self.results.keys())
|
|
leach_rspi = []
|
|
leachc_rspi = []
|
|
|
|
for scenario in scenarios:
|
|
leach_metrics = self.results[scenario]["LEACH"]["metrics"]
|
|
leachc_metrics = self.results[scenario]["LEACH-C"]["metrics"]
|
|
|
|
leach_rspi.append(leach_metrics.get("rspi", 0))
|
|
leachc_rspi.append(leachc_metrics.get("rspi", 0))
|
|
|
|
fig, ax = plt.subplots(figsize=(12, 6))
|
|
x_pos = range(len(scenarios))
|
|
width = 0.35
|
|
|
|
ax.bar([i - width/2 for i in x_pos], leach_rspi, width, label='LEACH', color='#FF6B6B')
|
|
ax.bar([i + width/2 for i in x_pos], leachc_rspi, width, label='LEACH-C', color='#4ECDC4')
|
|
|
|
ax.set_xlabel('Scénario', fontsize=12)
|
|
ax.set_ylabel('RSPI (0 à 1)', fontsize=12)
|
|
ax.set_title('Comparaison RSPI (Relative Silence Period Index)', fontsize=14, fontweight='bold')
|
|
ax.set_xticks(x_pos)
|
|
ax.set_xticklabels(scenarios, rotation=45, ha='right')
|
|
ax.set_ylim([0, 1.1])
|
|
ax.legend()
|
|
ax.grid(axis='y', alpha=0.3)
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(f"{output_dir}/04_RSPI_Comparison.png", dpi=300)
|
|
plt.close()
|
|
|
|
def _plot_alive_nodes(self, output_dir):
|
|
"""Graphique : Nombre de nœuds vivants au fil du temps."""
|
|
scenarios = list(self.results.keys())[:3] # Premiers 3 scénarios
|
|
|
|
fig, axes = plt.subplots(len(scenarios), 2, figsize=(14, 4*len(scenarios)))
|
|
|
|
for idx, scenario in enumerate(scenarios):
|
|
# LEACH
|
|
leach_detailed = self.results[scenario]["LEACH"]["detailed_rounds"]
|
|
rounds = [r["round"] for r in leach_detailed]
|
|
alive = [r["alive_nodes"] for r in leach_detailed]
|
|
|
|
axes[idx, 0].plot(rounds, alive, marker='o', label='LEACH', color='#FF6B6B')
|
|
axes[idx, 0].set_xlabel('Round')
|
|
axes[idx, 0].set_ylabel('Nœuds Vivants')
|
|
axes[idx, 0].set_title(f'LEACH - {scenario}')
|
|
axes[idx, 0].grid(alpha=0.3)
|
|
|
|
# LEACH-C
|
|
leachc_detailed = self.results[scenario]["LEACH-C"]["detailed_rounds"]
|
|
rounds = [r["round"] for r in leachc_detailed]
|
|
alive = [r["alive_nodes"] for r in leachc_detailed]
|
|
|
|
axes[idx, 1].plot(rounds, alive, marker='s', label='LEACH-C', color='#4ECDC4')
|
|
axes[idx, 1].set_xlabel('Round')
|
|
axes[idx, 1].set_ylabel('Nœuds Vivants')
|
|
axes[idx, 1].set_title(f'LEACH-C - {scenario}')
|
|
axes[idx, 1].grid(alpha=0.3)
|
|
|
|
plt.tight_layout()
|
|
plt.savefig(f"{output_dir}/05_Alive_Nodes_Over_Time.png", dpi=300)
|
|
plt.close()
|
|
|
|
def generate_summary_table(self, output_file):
|
|
"""
|
|
Génère un tableau récapitulatif en CSV.
|
|
|
|
Args:
|
|
output_file (str): Chemin du fichier CSV
|
|
"""
|
|
with open(output_file, 'w') as f:
|
|
# En-tête
|
|
f.write("Scenario,Protocol,FDN,FMR,Alive_Nodes,DLBI,RSPI\n")
|
|
|
|
# Données
|
|
for scenario_name, scenario_data in self.results.items():
|
|
for protocol in ["LEACH", "LEACH-C"]:
|
|
metrics = scenario_data[protocol]["metrics"]
|
|
|
|
f.write(f"{scenario_name},{protocol},")
|
|
f.write(f"{metrics.get('first_dead_node_round', 'N/A')},")
|
|
f.write(f"{metrics.get('first_muted_round', 'N/A')},")
|
|
f.write(f"{metrics.get('final_alive_nodes', 'N/A')},")
|
|
f.write(f"{metrics.get('dlbi', 'N/A'):.4f},")
|
|
f.write(f"{metrics.get('rspi', 'N/A'):.4f}\n")
|
|
|
|
print(f"OK - Tableau récapitulatif: {output_file}")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
analyzer = ResultsAnalyzer("/home/paul/algo/results/simulation_results.json")
|
|
analyzer.generate_comparison_graphs("/home/paul/algo/results")
|
|
analyzer.generate_summary_table("/home/paul/algo/results/summary.csv")
|