DM
Autour du sĂ©quençage du gĂ©nomeâïž
Dans ce sujet, on sâintĂ©resse Ă la recherche dâun motif dans une molĂ©cule dâADN.
Une molĂ©cule dâADN est constituĂ©e de deux brins complĂ©mentaires, qui sont un long enchaĂźnement de nuclĂ©otides de quatre types diffĂ©rents dĂ©signĂ©s par les lettres A, T, C et G. Les deux brins sont complĂ©mentaires : "en face" dâun âAâ, il y a toujours un âTâ et "en face" dâun âCâ, il y a toujours un âGâ. Pour simplifier le sujet, on va considĂ©rer quâune molĂ©cule dâADN est une chaĂźne de caractĂšres sur lâalphabet {A,C,G,T} (on sâintĂ©resse donc seulement Ă un des deux brins). On parlera de sĂ©quence dâADN.
Partie I - GĂ©nĂ©ration dâune sĂ©quence dâADNâïž
On considĂšre la chaĂźne de caractĂšre seq=âATCGTACGTACGâ
.
Q1. Que renvoie la commande seq[3]
? Que renvoie la commande seq[2:6]
?
Les fonctions que nous allons construire par la suite devront prendre en paramĂštre une chaĂźne de caractĂšres ne contenant que des âAâ, âCâ, âGâ et âTâ (ceci correspond Ă une sĂ©quence dâADN). Nous allons commencer par construire alĂ©atoirement une sĂ©quence dâADN.
Pour gĂ©nĂ©rer alĂ©atoirement une sĂ©quence dâADN composĂ©e de n caractĂšres, on utilisera le principe suivant.
-
On commence par créer une chaßne de caractÚres vide.
-
Puis on tire aléatoirement n chiffres compris entre 1 et 4 et
-
si on obtient un 1, alors on ajoute un âAâ Ă notre chaĂźne de caractĂšres ;
-
si on obtient un 2, alors on ajoute un âCâ Ă notre chaĂźne de caractĂšres ;
-
si on obtient un 3, alors on ajoute un âGâ Ă notre chaĂźne de caractĂšres ;
-
si on obtient un 4, alors on ajoute un âTâ Ă notre chaĂźne de caractĂšres.
-
On renvoie la chaĂźne de caractĂšres ainsi construite.
Q2. Ăcrire une fonction generation()
qui prend en paramĂštre un entier n et qui renvoie une chaĂźne de caractĂšres alĂ©atoires de longueur n ne contenant que des âAâ, âCâ, âGâ et âTâ.
On pourra utiliser la fonctions randint()
de random
.
Q3. Que fait la fonction mystere(seq)
qui prend en argument une sĂ©quence dâADN âseqâ (une chaĂźne de caractĂšres ne contenant que des âAâ, âCâ, âGâ et âTâ) ?
def mystere(seq):
a,b,c,d = 0,0,0,0
i = len(seq)â1
while i>= 0:
if seq[i]=='A':
a += 1
i â= 1
elif seq[i]=='C':
b += 1
i â= 1
elif seq[i]=='G':
c += 1
i â= 1
else:
d += 1
i â= 1
return [a*100/len(seq),b*100/len(seq),c*100/len(seq),d*100/len(seq)]
Q4. Quelle est la complexité de la fonction mystere()
?
Donner le nom de la variable permettant de montrer la terminaison de lâalgorithme.
Partie II - Recherche dâun motifâïž
Soit une chaĂźne de caractĂšres S=âACTGGTCACTâ
, on appelle sous-chaĂźne de caractĂšres de S unesuite de caractĂšres incluse dans S. Par exemple, âTGGâ est une sous-chaĂźne de S mais âTAGâ nâest pas une sous-chaĂźne de S.
Objectif
Rechercher une sous-chaßne de caractÚres M de longueur m appelée motif dans une chaßne de caractÚres S de longueur n.
Il sâagit dâune problĂ©matique classique en informatique, qui rĂ©pond aux besoins de nombreuses applications.
On trouve plus de 100 algorithmes diffĂ©rents pour cette mĂȘme tĂąche, les plus cĂ©lĂšbres datant des annĂ©es 1970, mais plus de la moitiĂ© ont moins de 10 ans. Dans cette partie, nous allons dâabord nous intĂ©resser Ă lâalgorithme naĂŻf , puis Ă deux autres algorithmes : lâalgorithme de Knuth-Morris-Pratt, et un algorithme utilisant une structure de liste .
Les différentes sous-parties sont indépendantes.
II.1 - Algorithme naĂŻfâïž
Principe de lâalgorithme naĂŻf
On parcourt la chaĂźne. Ă chaque Ă©tape, on regarde si on a trouvĂ© le bon motif. Si ce nâest pas le cas, on recommence avec lâĂ©lĂ©ment suivant de la chaĂźne de caractĂšres.
Cet algorithme a une complexité en O(nm)
avec n, la taille de la chaĂźne de caractĂšre et m, la taille du motif.
Q5. Ăcrire une fonction recherche()
qui Ă une sous-chaĂźne de caractĂšres M et une chaĂźne de caractĂšres S renvoie -1 si M nâest pas dans S, et la position de la premiĂšre lettre de la chaĂźne de caractĂšres M si M est prĂ©sente dans S.
Cet algorithme doit correspondre Ă lâalgorithme naĂŻf.
Q6. Combien faut-il dâopĂ©rations pour chercher un motif de 50 caractĂšres dans une sĂ©quence dâADN en utilisant lâalgorithme naĂŻf ? On supposera quâune sĂ©quence dâADN est composĂ©e de \(3 · 10^9\) caractĂšres. En combien de temps un ordinateur rĂ©alisant \(10^{12}\) opĂ©rations par seconde fait-il ce calcul ?
En gĂ©nĂ©tique, on utilise des algorithmes de recherche pour identifier les similaritĂ©s entre deux sĂ©quences dâADN. Pour cela, on procĂšde de la maniĂšre suivante :
-
dĂ©couper la premiĂšre sĂ©quence dâADN en morceaux de taille 50 ;
-
rechercher chaque morceau dans la deuxiĂšme sĂ©quence dâADN.
Q7. En utilisant les calculs prĂ©cĂ©dents, combien de temps faut-il pour un ordinateur rĂ©alisant \(10^{12}\) opĂ©rations par seconde pour comparer deux sĂ©quences dâADN avec lâalgorithme naĂŻf ?
Vous semble-t-il intĂ©ressant dâutiliser lâalgorithme de recherche naĂŻf ?
II.2 - Algorithme de Knuth-Morris-Pratt (1970)âïž
Lorsquâun Ă©chec a lieu dans lâalgorithme naĂŻf, câest-Ă -dire lorsquâun caractĂšre du motif est diffĂ©rent du caractĂšre correspondant dans la sĂ©quence dâADN, la recherche reprend Ă la position suivante en repartant au dĂ©but du motif. Si le caractĂšre qui a provoquĂ© lâĂ©chec nâest pas au dĂ©but du motif, cette recherche commence par comparer une partie du motif avec une partie de la sĂ©quence dâADN qui a dĂ©jĂ Ă©tĂ© comparĂ©e avec le motif. LâidĂ©e de dĂ©part de lâalgorithme de Knuth-Morris-Pratt est dâĂ©viter ces comparaisons inutiles. Pour cela, une fonction annexe qui recherche le plus long prĂ©fixe dâun motif qui soit aussi un suffixe de ce motif est utilisĂ©e.
Avant dâĂ©tudier lâalgorithme de Knuth-Morris-Pratt nous allons dĂ©finir les notions de prĂ©fixe et suffixe.
II.2.a PrĂ©fixe et suffixeâïž
Un prĂ©fixe dâun motif M est un motif u, diffĂ©rent de M, qui est un dĂ©but de M. Par exemple, âmoâ et âmâ sont des prĂ©fixes de âmotâ, mais âoâ nâest pas un prĂ©fixe de âmotâ .
Un suffixe dâun motif M est un motif u, diffĂ©rent de M, qui est une fin de M.
Par exemple, âotâ et âtâ sont des suffixes de âmotâ, mais âmotâ nâest pas un suffixe de âmotâ.
Q8. Donner tous les prĂ©fixes et les suffixes du motif âACGTACâ.
Q9. Quel est le plus grand prĂ©fixe de âACGTACâ qui soit aussi un suffixe ?
Quel est le plus grand prĂ©fixe de âACAACAâ qui soit aussi un suffixe ?
II.2.b Algorithme de Knuth-Morris-Prattâïž
Nous rappelons que lâalgorithme de Knuth-Morris-Pratt (KMP) est une fonction de recherche qui utilise une fonction annexe prenant en argument une chaĂźne de caractĂšres M dont on notera la longueur m.
Cette fonction annexe, appelée fonctionannexe()
, doit permettre, pour chaque lettre Ă la position i, de trouver le plus grand sous-mot de M qui finit par la lettre M[i]
(câest donc le plus grand suffixe de M[ :i+1]
) qui soit aussi un préfixe de M.
Le code de fonctionannexe()
se trouve Ă la question Q11 du DR 6.
def fonctionannexe(M):
F=[0]
i=1
j=0
while i < m :
if M[i]=M[j] :
F.append(j+1)
i=i+1
j=j+1
else
if j>0 :
j=F[jâ1]
else:
F.append(0)
i=i+1
return F
Q10. Quel est le type de la sortie de la fonction fonctionannexe()
?
Q11. Une ou des erreurs de syntaxe sâest (se sont) glissĂ©e(s) dans la fonction fonctionannexe()
.
Identifier la ou les erreur(s) et corriger la fonction pour quâil nây ait plus de message dâerreur quand on exĂ©cute la fonction.
Q12. DĂ©crire lâexĂ©cution de la fonction fonctionannexe()
lorsque M=âACAACAâ en prĂ©cisant sur le pour les six premiers tours dans la boucle while, Ă la sortie de la boucle, le contenu des variables : i, j et F.
Q13. Lâalgorithme KMP.
1 def KMP(M,T):
2 F=fonctionannexe(M)
3 i=0
4 j=0
5 while i < len(T) :
6 if T[i]==M[j]:
7 if j==len(M)â1:
8 return(iâj)
9 else:
10 i=i+1
11 j=j+1
12 else:
13 if j > 0:
14 j=F[jâ1]
15 else:
16 i=i+1
17 return â1
Expliquer la ligne 2, expliquer les lignes 3 et 4.
Quelles lignes correspondent au cas oĂč on a trouvĂ© le mot ?
Que fait le programme dans ce cas ?
II.3 - Algorithme utilisant la structure de listeâïž
Une autre possibilitĂ© pour chercher un motif dans une chaĂźne de caractĂšres (ou sĂ©quence dâADN) est de construire une liste contenant tous les sous-motifs de notre chaĂźne, triĂ©s par ordre alphabĂ©tique, puis de faire la recherche dans cette liste. Par exemple, Ă la chaĂźne âCATCGâ, on peut lui associer la liste :
[âCâ,âAâ,âTâ,âGâ,âCAâ,âATâ,âTCâ,âCGâ,âCATâ,âATCâ,âTCGâ,âCATCâ,âATCGâ,âCATCGâ] que lâon peut ensuite trier pour obtenir la liste :
[âAâ,âATâ,âATCâ,âATCGâ,âCâ,âCAâ,âCATâ,âCATCâ,âCATCGâ,âCGâ,âGâ,âTâ,âTCâ,âTCGâ].
La premiÚre étape de cette méthode est donc de trier une liste.
Q14. Ăcrire une fonction triinsertion()
de tri par insertion dâune liste de nombres.
Q15. Comment peut-on adapter la fonction triinsertion()
Ă une liste de chaĂźne de caractĂšres ?
AprÚs avoir obtenu une liste triée, on peut faire une recherche dichotomique dans cette nouvelle liste.
Q16. Ăcrire une fonction recherchedichotomique()
de recherche dichotomique dans une liste de nombres triés.
Quel est lâintĂ©rĂȘt de ce type dâalgorithme (on parlera de complexitĂ©) ?