04-implementation.tex 8,35 ko
Newer Older
\section{Implémentation}

\subsection{Architecture Logicielle}

Le projet est implémenté selon une architecture client-serveur moderne:

\begin{itemize}
    \item \textbf{Backend}: Python 3.12 + FastAPI
    \item \textbf{Frontend}: React + TypeScript + Material-UI
    \item \textbf{Monorepo}: Structure Turborepo pour gestion unifiée
\end{itemize}

\subsection{Backend - Simulation Événementielle}

\subsubsection{Architecture du Simulateur}

Le simulateur utilise une approche \textbf{événementielle discrète}:

\begin{lstlisting}[language=Python, caption=Structure principale du simulateur]
class Simulator:
    def __init__(self, config: SimulationConfig):
        self.event_queue = []  # File de priorite (heapq)
        self.coordinator = MMOneQueue("coordinator", mu_c)
        self.servers = {id: MMOneQueue(id, mu_i) for ...}
        self.router = Router(p, [q1, q2, ...])

    def run(self) -> SimulationResults:
        # Echauffement (warmup)
        while time < warmup_time:
            process_events()

        # Collecte statistiques
        while time < simulation_time:
            process_events()
            collect_time_series()  # Toutes les 1000 unites

        return generate_results()
\end{lstlisting}

\subsubsection{Types d'Événements}

Deux types d'événements sont gérés:

\begin{enumerate}
    \item \textbf{ARRIVAL}: Arrivée d'une requête externe au coordinateur
    \begin{itemize}
        \item Ajout à la file du coordinateur
        \item Démarrage du service si coordinateur idle
        \item Planification de la prochaine arrivée (exponentielle)
    \end{itemize}

    \item \textbf{SERVICE\_END}: Fin de service à une station
    \begin{itemize}
        \item Retrait de la requête de la station
        \item Décision de routage (probabiliste)
        \item Envoi vers destination ou sortie système
        \item Démarrage du service suivant si file non vide
    \end{itemize}
\end{enumerate}

\subsubsection{Génération Aléatoire}

Les nombres aléatoires exponentiels sont générés par transformation inverse:

\begin{equation}
    X \sim \text{Exp}(\lambda) \Rightarrow X = -\frac{1}{\lambda}\ln(1-U), \quad U \sim \mathcal{U}(0,1)
\end{equation}

\begin{lstlisting}[language=Python, caption=Génération exponentielle]
def exponential_random(rate: float) -> float:
    """Generation nombre aleatoire exponentiel"""
    return -math.log(1 - random.random()) / rate
\end{lstlisting}

\subsubsection{Routage Probabiliste}

Le routage depuis le coordinateur utilise la méthode de sélection par inversion:

\begin{lstlisting}[language=Python, caption=Routage probabiliste]
def route_from_coordinator(self) -> Optional[str]:
    """Decide destination depuis coordinateur"""
    r = random.random()

    # Sortie du systeme avec probabilite p
    if r < self.exit_prob:
        return None

    # Selection serveur selon q_i
    cumulative = self.exit_prob
    for i, (server_id, prob) in enumerate(...):
        cumulative += prob
        if r < cumulative:
            return server_id
\end{lstlisting}

\subsubsection{Collecte des Statistiques}

Trois types de données sont collectés:

\begin{enumerate}
    \item \textbf{Métriques agrégées}: Temps moyens, utilisations, compteurs
    \item \textbf{Séries temporelles}: Échantillonnage périodique (1000 unités)
    \begin{lstlisting}[language=Python, caption=Collecte séries temporelles]
def collect_time_series_sample(self):
    total_customers = 0
    for queue in all_queues:
        n = len(queue.waiting) + (1 if queue.busy else 0)
        total_customers += n

    self.timestamps.append(current_time)
    self.customers_in_system.append(total_customers)
    \end{lstlisting}

    \item \textbf{Histogrammes}: Distribution des temps de traitement (20 bins)
    \begin{lstlisting}[language=Python, caption=Génération histogramme]
def create_histogram(data: List[float]) -> dict:
    bins = np.linspace(min(data), max(data), 21)
    frequencies, _ = np.histogram(data, bins)
    return {
        "bins": bins.tolist(),
        "frequencies": frequencies.tolist(),
        "mean": np.mean(data),
        "std_dev": np.std(data)
    }
    \end{lstlisting}
\end{enumerate}

\subsection{Module d'Analyse Analytique}

Le module \texttt{analytics/jackson.py} implémente le théorème de Jackson:

\subsubsection{Calcul des Taux d'Arrivée Effectifs}

\begin{lstlisting}[language=Python, caption=Taux d'arrivée effectifs]
def compute_effective_arrival_rates(config):
    """Calcule lambda_eff selon theoreme de Jackson"""
    lambda_external = config.arrival_rate
    p = config.coordinator_exit_probability

    # Lambda coordinateur: lambda/(1-p) = lambda/p
    lambda_coord = lambda_external / p

    # Lambda serveurs: lambda * q_i / p
    lambda_servers = {}
    for server in config.servers:
        lambda_i = lambda_external * server.routing_prob / p
        lambda_servers[server.id] = lambda_i

    return lambda_coord, lambda_servers
\end{lstlisting}

\subsubsection{Métriques M/M/1}

\begin{lstlisting}[language=Python, caption=Calcul métriques M/M/1]
def compute_mm1_metrics(lambda_eff, mu):
    """Metriques pour une file M/M/1"""
    rho = lambda_eff / mu

    if rho >= 1:
        return {"stable": False, "utilization": rho}

    L = rho / (1 - rho)
    W = 1 / (mu - lambda_eff)
    Wq = rho / (mu - lambda_eff)

    return {
        "stable": True,
        "utilization": rho,
        "average_customers": L,
        "average_time": W,
        "average_wait_time": Wq
    }
\end{lstlisting}

\subsection{Interface Web}

\subsubsection{Architecture Frontend}

\begin{itemize}
    \item \textbf{Framework}: React 18 + TypeScript
    \item \textbf{UI Library}: Material-UI (MUI) v5
    \item \textbf{State Management}: Zustand
    \item \textbf{Charts}: Chart.js + react-chartjs-2
    \item \textbf{Network Diagrams}: D3.js
    \item \textbf{Build}: Vite
\end{itemize}

\subsubsection{Composants Principaux}

\begin{enumerate}
    \item \textbf{ScenarioSelector}: Sélection scénarios prédéfinis
    \item \textbf{ParameterPanel}: Configuration manuelle $\lambda$, $\mu_c$, $p$, $q_i$
    \item \textbf{SimulationControl}: Démarrage/arrêt simulation
    \item \textbf{ResultsDisplay}: Affichage résultats (onglets)
    \begin{itemize}
        \item Métriques: Tableaux détaillés
        \item Visualisations: Graphiques avancés
        \item Comparaison: Tables comparatives sim vs analytique
    \end{itemize}
    \item \textbf{TimeSeriesChart}: Évolution nombre de clients
    \item \textbf{ProcessingTimeHistogram}: Distribution temps traitement
    \item \textbf{NetworkDiagram}: Topologie réseau (D3.js)
\end{enumerate}

\subsubsection{Flux de Données}

\begin{enumerate}
    \item Utilisateur configure paramètres ou sélectionne scénario
    \item Frontend envoie requête POST à \texttt{/api/simulation/start}
    \item Backend exécute simulation (20-30 secondes)
    \item Résultats retournés avec time\_series et histogram
    \item Frontend calcule analytique via \texttt{/api/analytics/jackson}
    \item Comparaison via \texttt{/api/analytics/compare}
    \item Visualisations rendues avec Chart.js
\end{enumerate}

\subsection{Tests et Validation}

\subsubsection{Tests Unitaires Backend}

21 tests pytest couvrant:

\begin{itemize}
    \item Génération nombres aléatoires exponentiels (moyenne, reproductibilité)
    \item Simulation simple M/M/1 (validation contre formules)
    \item Détection systèmes instables
    \item Multi-serveurs avec routage
    \item Analyse Jackson (Little's Law, conservation probabilités)
\end{itemize}

\textbf{Résultat}: \texttt{21/21 tests PASSED}

\subsubsection{Tests d'Intégration}

8 tests shell automatisés:

\begin{enumerate}
    \item Backend health check
    \item Listing scénarios
    \item Exécution scénario
    \item Récupération résultats
    \item Analyse Jackson
    \item Frontend accessible
    \item CORS configuré
\end{enumerate}

\textbf{Résultat}: \texttt{8/8 tests PASSED}

\subsection{Performance}

\begin{table}[H]
\centering
\caption{Performance de l'implémentation}
\label{tab:performance}
\begin{tabular}{lll}
\toprule
\textbf{Métrique} & \textbf{Valeur} & \textbf{Commentaire} \\
\midrule
Temps simulation & 15-30s & Pour 100,000 unités temps \\
Événements/seconde & $\sim$30,000 & Sur machine standard \\
Mémoire backend & <100 MB & Efficacité Python \\
Bundle frontend & 720 KB & gzip: 231 KB \\
Tests backend & 0.19s & 21 tests \\
\bottomrule
\end{tabular}
\end{table}