Aller au contenu

Modélisez un processus de naissance et de mort

Dans une file d’attente, les clients arrivent un par un et repartent un par un. Dans un atelier, les machines tombent en panne une à une et sont réparées une à une. Dans une population, les individus naissent et meurent un à la fois. Tous ces systèmes ont un point commun : l’état est un nombre, et il ne bouge que de plus un ou de moins un.

Cette structure très particulière rend les calculs remarquablement simples : le régime stationnaire s’obtient par une formule explicite, sans résoudre de système. Ce chapitre vous la donne, et elle servira de moteur à toute la partie 3 sur les files d’attente. Notre fil rouge : un petit atelier de trois machines et un seul réparateur.

Un atelier de fabrication possède trois machines identiques. Chacune, quand elle fonctionne, tombe en panne au taux λ=0,1\lambda = 0{,}1 par heure (10 heures de fonctionnement en moyenne). Un seul technicien les répare, une à la fois, en une durée exponentielle de taux μ=0,5\mu = 0{,}5 par heure (2 heures en moyenne). Les durées sont indépendantes.

On note XtX_t le nombre de machines en panne à l’instant tt (qu’elles soient en réparation ou en attente). Les états possibles sont 0, 1, 2 et 3. Que peut-il se passer à partir de l’état nn ?

  • Une panne fait passer de nn à n+1n + 1. Il y a 3−n3 - n machines en marche, chacune avec une horloge exponentielle de taux λ\lambda ; la première panne survient au taux (3−n)λ(3 - n)\lambda (les taux s’additionnent, chapitre 5).
  • Une réparation fait passer de nn à n−1n - 1, au taux μ\mu dès qu’au moins une machine est en panne (le technicien ne répare qu’une machine à la fois).

Deux événements simultanés ont une probabilité négligeable : l’état ne saute jamais de deux unités d’un coup.

Un processus de naissance et de mort est une chaîne de Markov à temps continu à valeurs dans N\mathbb N (ou dans {0,…,K}\lbrace 0, \dots, K \rbrace) dont les seules transitions sont n→n+1n \to n+1 et n→n−1n \to n-1. Sur un petit intervalle de durée hh :

pn,n+1(h)=λnh+o(h),pn,n−1(h)=μnh+o(h),pnm(h)=o(h) si ∣n−m∣≥2.p_{n,n+1}(h) = \lambda_n h + o(h), \qquad p_{n,n-1}(h) = \mu_n h + o(h), \qquad p_{nm}(h) = o(h) \text{ si } |n - m| \geq 2.
  • λn\lambda_n est le taux de naissance dans l’état nn (arrivée d’un client, panne d’une machine) ;
  • μn\mu_n est le taux de mort dans l’état nn (départ d’un client, fin d’une réparation), avec μ0=0\mu_0 = 0 puisqu’on ne peut pas descendre sous zéro.

Le graphe des taux est une simple ligne :

λ0 λ1 λ2 λ(n-1) λn
0 ─────► 1 ─────► 2 ─────► 3 ··· n-1 ───────► n ───────► n+1 ···
◄───── ◄───── ◄───── ◄─────── ◄───────
μ1 μ2 μ3 μn μ(n+1)

et le générateur est tridiagonal : sur la ligne nn, on trouve μn\mu_n juste avant la diagonale, λn\lambda_n juste après, et −(λn+μn)-(\lambda_n + \mu_n) sur la diagonale.

A=(−λ0λ000⋯μ1−(λ1+μ1)λ10⋯0μ2−(λ2+μ2)λ2⋯⋮⋱⋱⋱)A = \begin{pmatrix} -\lambda_0 & \lambda_0 & 0 & 0 & \cdots \\ \mu_1 & -(\lambda_1 + \mu_1) & \lambda_1 & 0 & \cdots \\ 0 & \mu_2 & -(\lambda_2 + \mu_2) & \lambda_2 & \cdots \\ \vdots & & \ddots & \ddots & \ddots \end{pmatrix}

Pour l’atelier : λ0=0,3\lambda_0 = 0{,}3, λ1=0,2\lambda_1 = 0{,}2, λ2=0,1\lambda_2 = 0{,}1, λ3=0\lambda_3 = 0 (plus aucune machine ne peut tomber en panne) et μ1=μ2=μ3=0,5\mu_1 = \mu_2 = \mu_3 = 0{,}5.

pannes, au taux (3 − n) × 0,1réparations, au taux 0,5 (un seul technicien)01230,30,50,20,50,10,5
Le graphe de l'atelier est une ligne : on monte d'un cran à chaque panne, à un taux qui baisse avec le nombre de machines encore en marche, et on descend d'un cran à chaque réparation, toujours au taux 0,5.

Le régime transitoire : des équations en chaîne

Section intitulée « Le régime transitoire : des équations en chaîne »

L’équation de Kolmogorov p′(t)=p(t) Ap'(t) = p(t)\,A prend ici une forme très lisible :

p0′(t)=−λ0 p0(t)+μ1 p1(t)p_0'(t) = -\lambda_0\, p_0(t) + \mu_1\, p_1(t) pn′(t)=λn−1 pn−1(t)−(λn+μn) pn(t)+μn+1 pn+1(t)(n≥1)p_n'(t) = \lambda_{n-1}\, p_{n-1}(t) - (\lambda_n + \mu_n)\, p_n(t) + \mu_{n+1}\, p_{n+1}(t) \quad (n \geq 1)

La probabilité d’être en nn augmente grâce aux naissances depuis n−1n - 1 et aux morts depuis n+1n + 1, et diminue de tout ce qui quitte nn. Pour un espace infini, c’est un système infini d’équations différentielles couplées ; sauf cas particuliers (comme le processus de Poisson du chapitre suivant), on ne sait pas le résoudre à la main. En pratique, on le résout numériquement sur un espace tronqué, ou on se contente du régime stationnaire, beaucoup plus simple.

0,02,55,07,510,012,515,017,520,0t (heures), atelier entièrement en marche à t = 00,00,20,40,60,81,0probabilité0,5300,3180,1270,025p₀(t) : 0 en pannep₁(t) : 1 en pannep₂(t) : 2 en pannep₃(t) : 3 en panne
Le système différentiel de l'atelier, résolu numériquement : partant de 0 panne, les probabilités se stabilisent en une dizaine d'heures sur les valeurs stationnaires (pointillés), que la suite du chapitre obtient sans aucun calcul différentiel.

La balance locale et la formule du régime stationnaire

Section intitulée « La balance locale et la formule du régime stationnaire »

Écrivons la balance globale (flux sortant = flux entrant) de l’état 0 : on ne sort de 0 que par une naissance, on n’y entre que par une mort depuis 1.

λ0 Π0=μ1 Π1.\lambda_0\, \Pi_0 = \mu_1\, \Pi_1.

Pour l’état 1, la balance globale s’écrit (λ1+μ1) Π1=λ0 Π0+μ2 Π2(\lambda_1 + \mu_1)\,\Pi_1 = \lambda_0\,\Pi_0 + \mu_2\,\Pi_2. En y retranchant l’égalité précédente, il reste λ1 Π1=μ2 Π2\lambda_1\,\Pi_1 = \mu_2\,\Pi_2. Par récurrence, on obtient pour tout nn :

λn Πn=μn+1 Πn+1.\lambda_n\, \Pi_n = \mu_{n+1}\, \Pi_{n+1}.

C’est l’équation de balance locale. Elle a une interprétation géométrique simple : coupez le graphe entre nn et n+1n + 1. Le seul moyen de franchir la coupure vers la droite est une naissance depuis nn, et le seul moyen de la franchir vers la gauche est une mort depuis n+1n + 1. En régime stationnaire, il passe autant de flux dans chaque sens.

En déroulant la balance locale, Πn=λn−1μn Πn−1=⋯\Pi_n = \dfrac{\lambda_{n-1}}{\mu_n}\,\Pi_{n-1} = \cdots, d’où la formule générale :

Πn=γn Π0avecγn=λ0 λ1⋯λn−1μ1 μ2⋯μn,Π0=(1+∑n≥1γn)−1.\Pi_n = \gamma_n\, \Pi_0 \quad \text{avec} \quad \gamma_n = \frac{\lambda_0\, \lambda_1 \cdots \lambda_{n-1}}{\mu_1\, \mu_2 \cdots \mu_n}, \qquad \Pi_0 = \left(1 + \sum_{n \geq 1} \gamma_n\right)^{-1}.
  • γn\gamma_n est le produit des taux de naissance de 0 à n−1n - 1, divisé par le produit des taux de mort de 1 à nn ;
  • Π0\Pi_0 vient de la normalisation ∑nΠn=1\sum_n \Pi_n = 1.
0 en panne123 (atelier arrêté)0,00,20,40,60,8Πₙ0,5300,3180,1270,0250,3 × 0,530= 0,5 × 0,318≈ 0,1590,2 × 0,318= 0,5 × 0,127≈ 0,0640,1 × 0,127= 0,5 × 0,025≈ 0,013à chaque coupure : flux montant = flux descendantmoyenne : 0,648machine en panne
La balance locale sur les chiffres de l'atelier : à chaque coupure, le flux qui monte (taux de panne × probabilité de l'état de gauche) égale le flux qui descend (0,5 × probabilité de l'état de droite).

Et quand l’espace d’états est infini ? Tout dépend de la convergence de ∑γn\sum \gamma_n. Deux cas fondamentaux, que vous retrouverez dans la partie 3 :

  • Taux constants λn=λ\lambda_n = \lambda, μn=μ\mu_n = \mu : alors γn=ρn\gamma_n = \rho^n avec ρ=λ/μ\rho = \lambda/\mu. La série géométrique converge si et seulement si ρ<1\rho < 1, et alors Πn=(1−ρ) ρn\Pi_n = (1 - \rho)\,\rho^n. C’est la file M/M/1. Si ρ≥1\rho \geq 1, il n’y a pas de régime stationnaire : la file grossit indéfiniment (ou erre sans jamais se stabiliser).
  • Morts proportionnelles λn=λ\lambda_n = \lambda, μn=n μ\mu_n = n\,\mu : alors γn=un/n!\gamma_n = u^n / n! avec u=λ/μu = \lambda/\mu, la série converge toujours (vers eue^u), et Πn=e−u un/n!\Pi_n = e^{-u}\,u^n/n! est une loi de Poisson. C’est la file M/M/∞.
012345678n0,00,20,4Πₙ0,2000,1600,128moyenne 4queue lentetaux constants (M/M/1), ρ = 0,8Πₙ = 0,2 × 0,8ⁿ : géométrique012345678n0,4490,3590,144moyenne 0,8queue très courtemorts proportionnelles (M/M/∞), u = 0,8Πₙ=e0,8ⁿ/n!:Poisson−0,8
Même rapport λ/μ = 0,8, deux comportements : avec un seul serveur (taux de mort constant), la loi géométrique a une longue queue et une moyenne de 4 ; quand chaque client a son serveur (morts proportionnelles à n), la loi de Poisson reste concentrée près de 0.

Voici une fonction générique, qui accepte les taux sous forme de fonctions de nn et tronque l’espace si nécessaire :

import numpy as np
def stationnaire_nm(taux_naissance, taux_mort, n_max):
"""Régime stationnaire d'un processus de naissance et de mort sur {0, ..., n_max}.
taux_naissance(n) = lambda_n, taux_mort(n) = mu_n (pour n >= 1)."""
gamma = np.ones(n_max + 1)
for n in range(1, n_max + 1):
gamma[n] = gamma[n - 1] * taux_naissance(n - 1) / taux_mort(n) # balance locale
return gamma / gamma.sum()
lam, mu = 0.1, 0.5
pi = stationnaire_nm(lambda n: (3 - n) * lam, lambda n: mu, n_max=3)
print(np.round(pi, 3)) # [0.53 0.318 0.127 0.025]
print((np.arange(4) * pi).sum()) # nombre moyen de machines en panne ≈ 0.648
# M/M/1 tronquée : si rho < 1, la troncature a un effet négligeable
pi_mm1 = stationnaire_nm(lambda n: 8.0, lambda n: 10.0, n_max=200)
print(pi_mm1[:3]) # ≈ [0.2 0.16 0.128] = (1 - rho) rho^n
  • Un processus de naissance et de mort est une chaîne à temps continu sur les entiers qui ne saute que de +1+1 (taux λn\lambda_n) ou de −1-1 (taux μn\mu_n, avec μ0=0\mu_0 = 0).
  • Son générateur est tridiagonal ; les équations du régime transitoire couplent chaque pnp_n à ses deux voisins et sont en général difficiles à résoudre.
  • En régime stationnaire, la balance locale λnΠn=μn+1Πn+1\lambda_n \Pi_n = \mu_{n+1}\Pi_{n+1} exprime l’égalité des flux à travers la coupure entre nn et n+1n+1.
  • Formule générale : Πn=γnΠ0\Pi_n = \gamma_n \Pi_0, γn=λ0⋯λn−1μ1⋯μn\gamma_n = \dfrac{\lambda_0\cdots\lambda_{n-1}}{\mu_1\cdots\mu_n}, Π0=(1+∑n≥1γn)−1\Pi_0 = (1 + \sum_{n\geq1}\gamma_n)^{-1}, si la série converge.
  • Taux constants : loi géométrique Πn=(1−ρ)ρn\Pi_n = (1-\rho)\rho^n si ρ=λ/μ<1\rho = \lambda/\mu < 1. Morts proportionnelles à nn : loi de Poisson de paramètre λ/μ\lambda/\mu.

Exercice · Un calcul direct

facile

Un processus de naissance et de mort sur {0,1,2}\lbrace 0, 1, 2 \rbrace a pour taux λ0=2\lambda_0 = 2, λ1=1\lambda_1 = 1, μ1=1\mu_1 = 1, μ2=2\mu_2 = 2. Écrivez son générateur et calculez sa loi stationnaire.

Voir la solution
A=(−2201−2102−2)A = \begin{pmatrix} -2 & 2 & 0 \\ 1 & -2 & 1 \\ 0 & 2 & -2 \end{pmatrix}

(chaque ligne somme à 0). On a γ1=λ0/μ1=2\gamma_1 = \lambda_0/\mu_1 = 2 et γ2=λ0λ1/(μ1μ2)=2/2=1\gamma_2 = \lambda_0\lambda_1/(\mu_1\mu_2) = 2/2 = 1. Donc Π0=1/(1+2+1)=1/4\Pi_0 = 1/(1 + 2 + 1) = 1/4 et Π=(14,12,14)\Pi = (\tfrac14, \tfrac12, \tfrac14). On vérifie la balance locale : λ0Π0=2×14=12=μ1Π1\lambda_0\Pi_0 = 2 \times \tfrac14 = \tfrac12 = \mu_1\Pi_1 et λ1Π1=12=μ2Π2\lambda_1\Pi_1 = \tfrac12 = \mu_2\Pi_2.

En code

import numpy as np
A = np.array([[-2, 2, 0],
[1, -2, 1],
[0, 2, -2]], dtype=float)
print(A.sum(axis=1)) # [0. 0. 0.]
# Formule produit : gamma_n = (lambda_0 ... lambda_{n-1}) / (mu_1 ... mu_n)
lam = [2, 1]
mu = [1, 2]
gamma = np.cumprod([1] + [l / m for l, m in zip(lam, mu)])
pi = gamma / gamma.sum()
print(pi) # [0.25 0.5 0.25]
print(pi @ A) # [0. 0. 0.] : Pi A = 0

Exercice · Embaucher un second technicien ?

moyen

Dans l’atelier du chapitre, on envisage d’embaucher un second technicien : deux machines peuvent alors être réparées en même temps.

  1. Quels taux changent ? Donnez les nouveaux μn\mu_n.
  2. Calculez la nouvelle loi stationnaire et le nombre moyen de machines en panne.
  3. Le gain vous paraît-il justifier l’embauche ?
Voir la solution
  1. Les taux de panne ne changent pas. Les réparations se font au taux μn=min⁡(n,2) μ\mu_n = \min(n, 2)\,\mu : μ1=0,5\mu_1 = 0{,}5, μ2=μ3=1\mu_2 = \mu_3 = 1.
  2. γ1=0,3/0,5=0,6\gamma_1 = 0{,}3/0{,}5 = 0{,}6 ; γ2=0,3×0,2/(0,5×1)=0,12\gamma_2 = 0{,}3 \times 0{,}2/(0{,}5 \times 1) = 0{,}12 ; γ3=0,3×0,2×0,1/(0,5×1×1)=0,012\gamma_3 = 0{,}3 \times 0{,}2 \times 0{,}1/(0{,}5 \times 1 \times 1) = 0{,}012. Donc Π0=1/1,732≈0,577\Pi_0 = 1/1{,}732 \approx 0{,}577 et
Π≈(0,577 ; 0,346 ; 0,069 ; 0,007).\Pi \approx (0{,}577 \,;\, 0{,}346 \,;\, 0{,}069 \,;\, 0{,}007).

Le nombre moyen de machines en panne vaut 0,346+2×0,069+3×0,007≈0,5060{,}346 + 2 \times 0{,}069 + 3 \times 0{,}007 \approx 0{,}506, contre 0,648 avec un seul technicien. 3. On gagne en moyenne 0,648−0,506≈0,140{,}648 - 0{,}506 \approx 0{,}14 machine en marche, soit environ 6 % de production en plus (2,492{,}49 machines en marche au lieu de 2,352{,}35). La probabilité d’arrêt total passe de 2,5 % à 0,7 %. Le premier technicien n’est occupé que 47 % du temps : l’embauche ne se justifie que si une machine arrêtée coûte très cher.

En code

import numpy as np
def stationnaire_nm(taux_naissance, taux_mort, n_max):
gamma = np.ones(n_max + 1)
for n in range(1, n_max + 1):
gamma[n] = gamma[n - 1] * taux_naissance(n - 1) / taux_mort(n)
return gamma / gamma.sum()
lam, mu = 0.1, 0.5
panne = lambda n: (3 - n) * lam
for techniciens in (1, 2):
pi = stationnaire_nm(panne, lambda n: min(n, techniciens) * mu, 3)
en_panne = (np.arange(4) * pi).sum()
print(techniciens, np.round(pi, 3), round(en_panne, 3), round(3 - en_panne, 2))
# 1 [0.53 0.318 0.127 0.025] 0.648 2.35
# 2 [0.577 0.346 0.069 0.007] 0.506 2.49

Exercice · Des clients découragés

difficile

Devant un guichet unique, les clients arrivent au taux λ\lambda, mais se découragent quand il y a du monde : lorsqu’il y a déjà nn personnes, un client qui se présente n’entre qu’avec probabilité 1/(n+1)1/(n+1). Le service est exponentiel de taux μ\mu.

  1. Justifiez que le nombre de personnes présentes est un processus de naissance et de mort, et donnez ses taux.
  2. Montrez que la loi stationnaire existe toujours et identifiez-la.
  3. Application : λ=3\lambda = 3 clients par heure, μ=2\mu = 2 par heure. Quelle est la probabilité que le guichet soit vide ? Combien de personnes sont présentes en moyenne ?
Voir la solution
  1. Les arrivées effectives se font au taux λn=λ/(n+1)\lambda_n = \lambda/(n+1) (un processus d’arrivées au taux λ\lambda dont on ne garde chaque arrivée qu’avec probabilité 1/(n+1)1/(n+1)), et les départs au taux μn=μ\mu_n = \mu pour n≥1n \geq 1. L’état ne varie que de ±1\pm 1 : c’est un processus de naissance et de mort.
  2. γn=λ⋅λ2⋯λnμn=unn!\gamma_n = \dfrac{\lambda \cdot \tfrac{\lambda}{2} \cdots \tfrac{\lambda}{n}}{\mu^n} = \dfrac{u^n}{n!} avec u=λ/μu = \lambda/\mu. La série ∑un/n!\sum u^n/n! converge toujours (vers eue^u), donc le régime stationnaire existe quels que soient λ\lambda et μ\mu, et Πn=e−u un/n!\Pi_n = e^{-u}\,u^n/n! : c’est une loi de Poisson de paramètre uu, la même que pour la file M/M/∞.
  3. u=1,5u = 1{,}5 : Π0=e−1,5≈0,223\Pi_0 = e^{-1{,}5} \approx 0{,}223, et le nombre moyen de personnes présentes est l’espérance de la loi de Poisson, u=1,5u = 1{,}5.

En code

import numpy as np
from scipy.stats import poisson
lam, mu, n_max = 3.0, 2.0, 60 # espace tronqué à 60 personnes
gamma = np.ones(n_max + 1)
for n in range(1, n_max + 1):
gamma[n] = gamma[n - 1] * (lam / n) / mu # lambda_{n-1} = lam / n, mu_n = mu
pi = gamma / gamma.sum()
print(pi[0], (np.arange(n_max + 1) * pi).sum()) # 0.2231 1.5
print(np.abs(pi - poisson.pmf(np.arange(n_max + 1), lam / mu)).max()) # 5.6e-17 : Poisson(1.5)