Voici deux propriétés proches de la propriété de Markov (simple ou forte).
pour la “propriété de Markov”: si (X1,X2,…,Xn,…) est une suite i.i.d. selon la
loi de X1 alors (Xp+1,Xp+2,…,Xp+n,…) est aussi une suite i.i.d. selon la loi de X1
indépendante de la tribu σ(X1,X2,…,Xp).
pour la “propriété de Markov forte”: si τ est un temps d’arrêt par rapport à la
filtration ℱn = σ(X1,…,Xn) alors (Xτ+1,Xτ+2,…,Xτ+n,…) est aussi une suite i.i.d.
selon la loi de X1 indépendante de la tribu σ(X1,X2,…,Xτ).
Donnons en quelques applications simples à des tirages indépendants à pile (p) ou face
(1 − p), (X1,X2,…,Xn,…).
Soit τP = inf{n ≥ 1,Xn = P}. On sait (ou on a oublié ...) que τP suit une loi géomètrique
de paramètre p. Si on a oublié, voici une façon simple de retrouver la fonction génératrice, on
a:
(1)
où τ′P suit la même loi que τP et est indépendante de X1 (c’est une conséquence de la
propriété de Markov). On en déduit que:
Ce qui donne la fonction génératrice de τP (sans calculs pénibles)
Il est facile de vérifier que c’est bien la fonction génératrice de la loi géométrique.
On obtient aussi, sans calcul, l’espérance de τP en prenant l’espérance de l’équation (1):
équation qui se résoud en E(τP) = 1∕p. Pour la variance on élève l’équation (1) au carré et
l’on prend l’espérance pour obtenir:
qui se résoud en E(τP2) = (1 + 2(1 − p)E(τP))∕p, puis Var(τP) = (1 − p)∕p2.
Lorsque p = 1∕2, on a ainsi E(τP) = 2 et Var(τP) = 2.
Les lois de τPF, τFP, τFF, τPP
On peut aussi calculer les lois de temps d’atteinte de “mots” de longueur 2. Par exemple si
τPF = inf{n ≥ 1,Xn−1 = P,Xn−1 = F}, il est facile de se convaincre (propriété de Markov
forte) que
et d’en déduire la moyenne, la variance et la fonction génératrice de τPF (exercice). On en
déduit, par exemple, immédiatement que lorsque p = 1∕2, E(τPF) = 2 + 2 = 4 et
Var(τPF) = 2 + 2 = 4!
Pour calculer la loi de τPP, c’est à peine plus compliqué, on écrit
où τPP(1) est indépendant de X1 et de même loi que τPP et τPP(2) est indépendant de
(X1,X2) et de même loi que τPP (propriété de Markov simple). On obtient la fonction
génératrice, la moyenne ou la variance par les mêmes techniques que précédemment.
Exercice 1. Effectuer les calculs suggérés précédemment pour calculer la moyenne, la
variance et la fonction génératrice de τPP.
Lorsque p = 1∕2, vérifier E(τPP) = 6 et Var(τPP) = 22.
Commentaires: on voit que les lois de τPF et τPP sont différentes, alors que les lois de
τPP et τFF sont identiques ainsi que celles de τPF et τFP (par un argument de symétrie).
Exercice 2. Montrer que P(X1 = F,τPPF> τFPP) = P(X1 = F) = 1∕2 (autrement
dit, si le premier tirage est un face, on a forcément τPPF> τFPP) et que P(X1 =
P,τPPF> τFPP) > 0. En déduire que P(τPPF> τFPP) > 1∕2.
Nous allons voir que l’on peut systématiser ce genre de technique pour obtenir la loi des
temps d’atteinte de tous les mots et ce pour tous les alphabets.
2 Le cadre général
On recherche un pattern M = (c1,…,cn), où n est la longueur du pattern, dans un chaine de
caractères (Si,i ≥ 1) supposé i.i.d. sur un alphabet fini E avec une loi donnée q = (qi,i ∈ E),
qi> 0 est supposé non nul pour tout i (sinon il suffit de retirer le caractère de l’alphabet
considéré).
On appelle τ le temps d’apparition du pattern dans la chaîne
Ce temps est fini presque sûrement, car plus petit que le produit de n fois une v.a. de loi
géometrique de probabilité de succés q(M) := ∏1nq(ci) > 0. Cela prouve aussi qu’il est
de moyenne et de variance finie (et, plus généralement, que tous ses moments sont
finis).
On va representer τ à l’aide d’une chaine de Markov (Zn,n ≥ 0) dont les états sont
(0,1,…,n). On identifie l’état j à la sous chaine de M, (c1,…,cj), où j represente le début du
pattern M de longueur j dont la coïncidence a été déjà vérifiée à la position i,
formellement:
avec, par convention, Zi = 0 lorsque l’ensemble est vide.
Lorsque et l’état Zi = n on a trouvé la chaîne M: τ est le temps d’atteinte de n par ce
processus.
Nous allons voir que Z est une chaîne de Markov et calculer sa matrice de transition.
Pour cela nous aurons besoin de la fonction overlap(x,y) qui à deux chaînes de caractères x
et y fait correspondre le plus long postfixe de la chaîne y qui est un suffixe de la chaîne x (voir
page 11 pour un code ScicosLab qui fait ce travail). Formellement, si ny est la longueur de y et
nx celle de x:
Avec cette notation on a:
Zi+1 est donc une fonction de Zi et de Si+1, ce qui prouve que c’est un chaîne de Markov et
l’on peut calculer sa matrice de transition.
La matrice de transition
Lorsque l’on est dans l’état i, à l’instant l, et que l’on considère le caractère suivant de la
chaîne S(l + 1)
1.
soit S(l + 1) = M(i + 1) et l’on passe à l’état i + 1
2.
sinon, on ne revient pas forcèment à l’état 0, mais on doit calculer le plus longpostfixe de (c(1),…,c(i),S(l+1)) qui est un prefixe de M (le résultat peut être vide,
bien sûr, auquel cas on revient en 0). Cette chaîne correspond à l’un des états
(0,…,l) et la transition se fait vers cet état.
Remarque 2.1.
Noter que l’on ne revient pas forcement en 0.
On a P(k,l) = 0, si l ≥ k + 2 et, pour tout l ≥ 1, P(l − 1,l) > 0. On utilisera par
la suite que P(n − 1,n) > 0.
On peut traiter les deux cas en même temps, puisque dans le cas 1, le plus long
prefixe correspond bien à i + 1. Ceci permet de simplifier la programmation.
Lorsque la suite S n’est plus iid mais est markovienne, on peut étendre le modèle
markovien mais l’espace d’état de la chaîne doit être augmenté (il faut rajouter
le caractère précedent à l’état lorsque la chaine revient en 0). La taille de l’espace
d’état est alors n + card(E) et il faut adapter le calcul de la matrice de transition.
On notera P(M,E,q) la matrice de transition ainsi obtenue et P lorsque le contexte
n’exige pas plus de précisions. P est une matrice de taille (n + 1) × (n + 1), si n est la
longueur du pattern. P est une généralisation de la matrice de la chaîne en “dents de
scie”.
Voir le code page 11 pour le code qui réalise le calcul de la matrice de la chaîne à partir des
données (la chaîne M, l’alphabet E et sa fréquence q).
Calcul de la fonction génératrice de la loi de τ
Soit ϕk(z) = Ek, la fonction génératrice de la loi de τ, lorsque la chaîne de Markov
démarre en k ∈{0, 1,…,n}. En utilisant la propriété de Markov, on vérifie que, pour tout
k ∈{0, 1,…,n − 1}
(3)
Exercice 3. Démontrer cette équation.
En tenant compte du fait que si y = n, τ = 0 et ϕn(z) = 1, on obtient l’équation, pour
x ∈{0, 1,…,n − 1}
On peut réécrire matriciellement cette équation sous la forme
(4)
où Q est la matrice n × n, Q = (P(i,j), 0 ≤ i ≤ n − 1, 0 ≤ j ≤ n − 1); ϕ∙(z) est le vecteur
colonne (ϕi(z), 0 ≤ i ≤ n − 1)′ et P(∙,n) le vecteur colonne (P(i,n), 0 ≤ i ≤ n − 1)′.
Nous allons voir que cette équation a une solution unique sur le corps de fractions
rationnelles d’inconnu z. En effet, si l’on a une solution à (I − zQ)u(z) = 0 avec u vecteur de
fractions rationnelles, on peut en multipliant u(z) par le produit des dénominateurs
du vecteur u(z), obtenir un vecteur de polynôme v(z) solution de v(z) = zQv(z).
Supposons un tel vecteur de polynome v de la forme v(z) = v0 + v1z + + vnzn alors
zPv(z) = zQv0 + z2Qv1 + + zn+1Qvn, et donc par récurrence v0 = = vn = 0. (I − zQ)
est donc injectif et donc surjectif si on le considère comme une matrice sur le corps des fractions
rationnelles. Ce qui prouve l’existence et l’unicité d’une fraction rationnelle solution
à l’équation (4). Ceci prouve aussi que ϕi(z) est une fraction rationelle pour tout
i ∈.
Voir le code page 12 pour l’implementation de ce calcul en Scilab (qui permet de
faire du calcul sur les fractions rationnelles sur R) et page 13 pour le même code en
Sage (qui permet de faire de l’arithmétique en précision illimitée à la différence de
Scilab).
3 Calcul des moments
Par dérivation il est facile d’obtenir une équation pour le calcul de la moyenne et de la
variance.
Calcul de la moyenne
Noter que ϕi(z) est un fraction rationelle donc peut toujours être dérivée comme fraction
rationelle autant de fois que souhaité. Par ailleurs, si ϕi(z) est représenté sous la
forme:
Pi et Qi étant deux polynômes sans facteurs communs, Qi(1) ⁄= 0 (car si Qi(1) = 0, Pi(1) ⁄= 0
et ϕi(1) = 1 est alors impossible). Il est facile d’en déduire que toutes les dérivées de ϕi(z)
calculé en z = 1 sont finies. Ce qui prouve que τ a des moments de tout ordre (ce que l’on a
déjà obtenu en majorant par un temps géométrique).
où ϕ′∙(z) est le vecteur colonne (ϕ′0(z),…,ϕ′n−1(z)). En prenant z = 1, on obtient en tenant
compte de ϕi(1) = 1
où 1 désigne le vecteur colonne (1,…, 1)′. Ce que l’on peut réécrire (il faut toutefois vérifier que 1 n’est pas
valeur propre de Q1 )
Calcul de la variance
En dérivant une deuxième fois l’équation (1) on obtient, pour i ∈
où ϕ′′∙(z) le vecteur colonne (ϕ′′0(z),…,ϕ′′n−1(z))′. Et en z = 1, on obtient
et donc (en tenant compte du fait que Q et (I − Q)−1 commutent
Noter que (Q1)i = 1 pour i = 0,…,n − 2 et que (Q1)n−1 = 1 − P(n − 1,n).
Pour les programmes qui suivent, on utilise plutôt la forme
Lorsque P est à coefficient rationnel on peut faire des calculs exacts à l’aide d’un logiciel de
calcul formel. (I − P) étant souvent difficile à inverser numériquement, ça peut être
utile.
Voici page 11 pour le code correspondant en ScicosLab ainsi que pour quelques exemples
d’utilisation.
4 Vers un algorithme efficace de recherche de pattern (Knuth-Morris-Pratt)
En s’inspirant de l’approche précédente, on peut concevoir un algorithme (proche de
l’algorithme KMP) qui permet de rechercher une chaîne de caractère dans un texte en
parcourant le texte séquentiellement (c’est à dire en avancant toujours de 1 caractère sans
jamais avoir à revenir en arrière ou à sauter en avant dans le texte, ce qui est commode voire
indispensable pour certain type de hardware). le programme qui suit n’est pas exactement
l’algorithme KMP, mais il en donne l’idée essentielle.
function res=search_pattern(M,Text) indice_partial_match=0; res=0; for i=1:length(Text)do if part(M,indice_partial_match+1:indice_partial_match+1)==part(Text,i)then indice_partial_match=indice_partial_match+1; if indice_partial_match==length(M)then res=i;return; end else proposition=part(M,1:indice_partial_match)+part(Text,i); // on calcule le nouvel indice de matching partiel indice_partial_match=length(overlap(M,proposition)); end end endfunction
Ecrire la fonction qui calcule le prefixe de longueur maximale de x qui est un suffixe de y
(ou de façon équivalente le suffixe de longueur maximale de y qui est un préfixe de x).
function res=overlap(x,y) // Calcule un prefixe de longueur maximale de x qui est un suffixe de y for i=length(x):-1:1do //QUESTION: prefixe = le prefixe de x de longueur i //REPONSE: prefixe = part(x,1:i); //QUESTION: suffixe = le suffixe de j de longueur i //REPONSE: suffixe = part(y,max(1,length(y)-i+1):length(y)); if (prefixe==suffixe)then res=prefixe;return; end end res=''; endfunction
Calculer la matrice de transition de la chaîne de markov en fonction du pattern M, de
l’alphabet E et de la loi de probabilité de cet alphabet q.
function res=inc(n) // sertà décaler de 1 les indices des matrices commencant en 0 res=n+1; endfunction function Matrice=markov_chain(M,E,q) // Calcule la matrice de transtion de la chaine de Markov // M : la chaîne recherchée, // E: l'aphabet, // q: la probabité de chaque lettre supposée i.i.d. selon cette loi card_alphabet=length(E); // Construction de la matrice de transition Matrice=zeros(length(M)+1,length(M)+1); for i=0:length(M)-1do for j=1:card_alphabetdo // On rajoute la lettre E(j)à l'état courant proposition=part(M,1:i)+part(E,j); // on calcule le nouvel etat grâceà la fonction overlap to=overlap(M,proposition); indice_etat=length(to);// l'indice de l'etat, c'est sa longueur // rajout de la probabilité q(j)à la transition de i -> "to" //QUESTION: Matrice(inc(i), inc(indice_etat)) = <À COMPLÉTER> //REPONSE: Matrice(inc(i), inc(indice_etat)) = ... //REPONSE: Matrice(inc(i), inc(indice_etat)) + q(j); end end // Lorsque l'on a atteint l'etat "length(M)", c'est gagné, on s'arrête. Matrice(inc(length(M)),inc(length(M)))=1; endfunction
function [moyenne,V]=moyenne_variance_tau(M,E,q) // Calcule la moyenne et la variance de |$\tau$| P=markov_chain(M,E,q); N=max(size(P))-1; Q=P(1:N,1:N); M=eye(N,N)-Q; M_moins_1=M^(-1);// calcule l'inverse la matrice M // Calcul de la moyenne |$\E(\tau)$| moyennes=M_moins_1*ones(N,1); //QUESTION: moyenne=<À COMPLÉTER>; //REPONSE: moyenne=moyennes(1,1); // Calcul de la variance //QUESTION: VV = <À COMPLÉTER>;// Calcul de |$\E(\tau(\tau-1))$| //REPONSE: VV = (M^(-1)) * 2 * Q * moyennes;// Calcul de |$\E(\tau(\tau-1))$| V=VV(1,1)+moyenne-moyenne^2;// On en déduit la variance. endfunction;
// Tirageà Pile ou Face alphabet="PF";proba_alphabet=[1/2,1/2]; W='P'; // loi géomètrique on doit trouver 2 et 2 [m,v]=moyenne_variance_tau(W,alphabet,proba_alphabet) W='FP'; // on doit trouver 4 et 4 [m,v]=moyenne_variance_tau(W,alphabet,proba_alphabet) W='PP'; // on doit trouver 6 et 22 [m,v]=moyenne_variance_tau(W,alphabet,proba_alphabet) // Cette loi est différente de la précedente
// Le génome, 4 bases CATG alphabet="CATG";proba_alphabet=[1/4,1/4,1/4,1/4]; W='CCTAAGGA' [m,v]=moyenne_variance_tau(W,alphabet,proba_alphabet)
function phi=fonction_generatrice(M,E,q) // Calcule la fonction génératrice de la loi de |$\tau$| // P est la matrice de transition de taille |$N+1\times N+1$| P=markov_chain(M,E,q); N=max(size(P))-1; // On resoud l'equation dans le corps des fractions rationnelles Q=P(1:N,1:N); Id=eye(N,N); z=poly(0,"z"); M=Id-z*Q; A=(1/M)*z*P(1:N,N+1);// 1/M calcule l'inverse la matrice M phi=A(1,1); endfunction;
6 Listing Sage
Malheureusement, on ne peut traiter que des chaînes de caractères longueur petite (≈ 10) si
l’on se contente de l’arithmétique en précision limitée standard. Pour traiter des chaînes plus
longues il faut faire du calcul en précision illimitée dans Q. Voici une implementation en
sage (on peut télécharger librement sage pour linux, macos ou windows sur le site
http://www.sagemath.org) pour un cas où M est plus long (longueur l = 43, on
néglige accents et majuscules mais on rajoute le ' ' à l’alphabet, de 27 lettres donc).
"Longtemps je me suis couché de bonne heure".
Cette chaîne est plutôt simple, puisque, lorsque l > 0 soit on passe de l à l + 1 avec proba 1∕27, on
retourne en 1 avec proba 1∕27 (cas d’échec mais avec comme nouvelle lettre 'l'), sinon on
retourne en 0 avec proba 25∕27. Le cas l = 0 est particulier, la probabilité de rester en 0 est de
26∕27 et d’aller en 1 de 1∕27.
def overlap(x,y):
# Calcule le plus long prefixe
# de x qui est un suffixe de y
l_y=len(y)
i=len(x)
while ((i>0) and (x[0:i] <> y[max(0,l_y-i):l_y])):
i=i-1
return x[0:i]
def markov_chain(M, E, q):
# Calcule la matrice de transition de la chaine de Markov
card_alphabet=len(E);
N=len(M);
MS=MatrixSpace(QQ,N+1,N+1)
Matrice=MS()
for i in [0..N-1]:
for j in [0..card_alphabet-1]:
# On rajoute la lettre E(j) a l'etat de la chaine
proposition=M[0:i]+E[j:j+1];
# on calcule le nouvel etat grace a la fonction overlap
to=overlap(M,proposition);
indice_etat=len(to) # l'indice de l'etat, c'est sa longueur
# on rajoute la probabilite de alphabet(j)
# a la transition de i vers "to"
Matrice[i, indice_etat] = Matrice[i,indice_etat] + q[j];
# Lorsque l'on a atteint l'etat "M=len(M)", c'est gagne, on s'arrete.
Matrice[N,N] = 1
return Matrice
def moyenne_variance(M, E, q):
# calcul la moyenne et la variance du temps d'atteinte de N
# par la chaine partant de 0 de matrice de transition P
P=markov_chain(M, E, q)
N=P.nrows()
Q=P[0:N-1,0:N-1]
#
MS=MatrixSpace(QQ,N-1,N-1)
Id=MS.one()
M=Id-Q;
#
VS=VectorSpace(QQ,N-1)
v=VS()
for i in [0..N-2]: v[i]=1
A=M.solve_right(v)
moyenne=A[0]
#
vv=2*Q*A
B=M.solve_right(vv)
variance=B[0]+moyenne-moyenne*moyenne
return [moyenne, variance]
# tirages à pile ou face
E='PF'
q=[1/2, 1/2]
moyenne_variance('P', E, q)
moyenne_variance('PF', E, q)
moyenne_variance('PP', E, q)
moyenne_variance('PFPFPFPFPF', E, q)
# alphabet classique
E='abcdefghijklmnopqrstuvwxyz'+' '
M='bonjour et bonjour'
N=len(M)
size=len(E);
VS=VectorSpace(QQ,size);
q=VS();
for i in [0..size-1]: q[i]=1/size;
[moyenne,variance]=moyenne_variance(M, E, q)
# Un exemple de très grande taille : 1000 caractères
def log10(x):
return ln(x)/ln(10)
N=1000
p=1/27
# Construit la matrice de transition d'une chaine generique qui :
# -> 0 avec proba 1-2*p, -> 1 avec proba p, n -> n+1 avec proba p
E='PFQ';q=[p,p,1-2*p];
# P suivi de (N-1) F
M='P';
for i in [1..N-1]: M=M+'F'
[moyenne,variance]=moyenne_variance(M, E, q)
log10(moyenne).n(digits=10)
# Esp |$\approx 10^{1431}$|
# que l'on peut comparer à la loi geometrique majorante
pp=(1/27)^N
moy_geom=N/pp
log10(moy_geom).n(digits=10)
# Esp |$\approx 10^{1434}$|
def fonction_gene(M, E, q):
# calcule la fonction generatrice
# qui est de la forme |$z^N / Pol(z)$|