Introduction à l`Algorithmique et la Programmation feuille de Projet

Transcription

Introduction à l`Algorithmique et la Programmation feuille de Projet
Introduction à l’Algorithmique et la Programmation
feuille de Projet Phylogénie
Le thème de ce projet est la construction et la manipulation d’arbres phylogénétiques. Il permet
d’illustrer comment les principes algorithmiques et de programmation vus durant les cours peuvent
être appliqués à l’aide de Python pour l’analyse et l’exploitation de données biologiques.
Un arbre phylogénétique représente un scénario d’évolution qui lie un ensemble d’espèces données. Chaque espèce constitue une feuille de l’arbre. Pour une paire quelconque d’espèces, on peut
déterminer leur ancêtre commun et le représenter comme un noeud dans l’arbre. Les 2 espèces
actuelles sont considérées comme les enfants de l’espèce ancestrale. A chaque espèce (ancestrale ou
non), on peut associer un nom pour la désigner, et un ensemble de caractéristiques morphologiques
et anatomiques spécifiques (aspect général, squelette, présence de certains organes...etc).
Par exemple, considérons l’arbre phylogénétique suivant :
Figure 1 – Arbre phylogénétique
Il relie 6 espèces actuelles : la lamproie, la bonite, le xénope, le crocodile, le kiwi et le cobaye. Ces
espèces sont reliées deux à deux par 5 ancêtres communs. L’ancêtre le plus éloigné, placé tout en
haut de l’arbre, est la racine. A chaque événement de spéciation (création de 2 nouvelles espèces) est
associée une innovation évolutive. Ainsi l’événement de spéciation au niveau de l’ancêtre commun
numéroté 1 est associé à l’apparition des doigts : le xénope, le crocodile, le kiwi et le cobaye
possèdent des doigts, alors que la bonite et la lamproie n’en ont pas. Notez, que les caractéristiques
morphologiques et anatomiques considérées pour cet arbre sont les mâchoires, les doigts, l’amnios,
le placenta et le gésier.
Exercice - 1 Représentation d’un arbre en Python
On pourra représenter un arbre phylogénétique en Python par un triplet (tuple contenant trois
éléments) formé de :
— une étiquette (le nom de l’espèce à la racine),
— une liste d’enfants (les espèces issues de la spéciation au niveau de la racine),
1
feuille de Projet Phylogénie
IAP 2013-2014
— une liste d’attributs (les caractéristiques morphologiques/anatomiques de l’espèce à la
racine).
L’étiquette est de type chaîne de caractères. Un enfant est lui-même un arbre. Un attribut est
représenté par une valeur booléenne Faux/Vrai ou 0/1, selon que cette caractéristique est absente
ou présente dans l’espèce.
L’arbre de la Figure 1 sera donc représenté par le triplet suivant :
(’Ancetre0’, [(’Lamproie’,[],[0,0,0,0,0]),(’Ancetre1’, [(’Bonite’, [], [1,0,0,0,0]),
(’Ancetre2’,[(’Xénope’, [], [1,1,0,0,0]), (’Ancetre3’, [(’Cobaye’, [], [1,1,1,1,0]),
(’Ancetre4’, [(’Crocodile’, [], [1,1,1,0,1]), (’Kiwi’, [], [1,1,1,0,1])], [1,1,1,0,1])],
[1,1,1,0,0])], [1,1,0,0,0])], [1,0,0,0,0])], [0,0,0,0,0]).
Pour plus de clarté de lecture, le nom et les attributs d’une même espèce ancestrale sont colorés
de la même manière.
La racine de l’arbre possède l’étiquette ’Ancetre0’ et 2 noeuds enfants, associés aux valeurs
’Lamproie’ et ’Ancetre1’ respectivement. Cette espèce ancestrale ne possède ni machoires, ni doigts,
ni amnios, ni placenta, ni gésier.
Le noeud associé à l’étiquette ’Ancetre3’ possède 2 enfants et peut être représenté par le triplet
suivant : (’Ancetre3’, [(’Cobaye’, [], [1,1,1,1,0]), (’Ancetre4’, [(’Crocodile’, [], [1,1,1,0,1]),
(’Kiwi’, [], [1,1,1,0,1])], [1,1,1,0,1])], [1,1,1,0,0]).
Le noeud associé à l’étiquette ’Xénope’ est une feuille, c’est-à-dire qu’il ne possède aucun enfant.
Il peut être représenté par le triplet suivant : (’Xénope’,[], [1,1,0,0,0)]).
1- Rappelez la définition d’une entité récursive.
2- Expliquez pourquoi un arbre est une entité récursive.
Exercice - 2 Construction et manipulation d’un arbre
Dans le fichier miniProjet_phylo.py sont définies deux fonctions Enfants(A) et Valeur(A), qui
permettent d’accéder à l’étiquette et aux enfants associés à la racine d’un arbre A.
1- Ecrivez les fonctions suivantes :
a- Attributs(A) qui renvoie les attributs de la racine de A ; si la racine n’a pas d’attribut, la
fonction renverra une liste vide
b- NbEnfants(A) qui renvoie le nombre d’enfants que possède la racine de A
c- EstFeuille(A) qui teste si A est une feuille et renvoie une donnée de type Booléen
d- CreeFeuille(etiquette, attributs) qui crée une feuille avec une étiquette et/ou des attributs
donnés (notez que cette fonction doit pouvoir être appelée en indiquant seulement une étiquette, sans attributs)
2- En programmation, il est important de mettre en place des contrôles pour s’assurer de la validité
des opérations effectuées et de la cohérence des données. Considérez attentivement les variables
ci-dessous :
a- [’Xénope’,[], [(’Machoires’,1),(’Doigts’,1)]]
b- ([(’Machoires’,1),(’Doigts’,1)],[], ’Xénope’)
c- (’Ancetre’, ((’Crocodile’, [],[(’Machoires’,1)]),(’Kiwi’, [],[(’Machoires’,1)])),[(’Machoires’,1)])
Ces variables représentent-elles des arbres phylogénétiques ? Pourquoi ? Proposez une fonction
estValide(A) qui teste si la racine d’un arbre A répond aux critères requis pour représenter un
arbre phylogénétique.
UPMC - Licence Biologie Mathématiques
2
feuille de Projet Phylogénie
IAP 2013-2014
3- On considère deux espèces, représentant les racines de deux arbres phylogénétiques. On veut
relier ces deux espèces par leur ancêtre commun.
a- Ecrivez une fonction FusionnerArbre(A1, A2, racine), qui permet de fusionner deux arbres
A1 et A2 en un nouvel arbre dont la racine a pour étiquette racine.
b- Modifiez cette fonction pour s’assurer que les deux racines des arbres A1 et A2 sont valides,
avant de procéder à la fusion. Vous utiliserez la fonction estValide(A) et vous vous inspirerez
de la syntaxe suivante : assert valeur_renvoyée_par_le_test, message_erreur
qui affiche un message message_erreur dans le cas où le test échoue, c’est-à-dire quand
valeur_renvoyée_par_le_test a pour valeur False.
Exercice - 3 Utilisation de la récurrence pour manipuler les arbres
Nous avons vu précédemment que les fonctions récursives sont très utiles pour calculer les
éléments d’une suite.
Par exemple, si on considère la suite de Fibonacci :
— u0 = 1
— u1 = 1
— un = un−1 + un−2
Dans le cas général, un élément de degré n de la suite de Fibonacci est calculé en faisant la
somme des deux élements précédents de degrés n − 1 et n − 2. Les éléments u0 et u1 représentent
des cas particuliers.
Pour calculer un élément de cette suite, on peut définir une fonction récursive Fibo(n) qui prend
en paramètre d’entrée le degré n de l’élément que l’on veut calculer et qui renvoie cet élément.
Fibo(n):
if n==0 or n==1:
return 1
else:
return Fibo(n-1) + Fibo(n-2)
Comme les arbres peuvent être construits de manière récursive, les fonctions récursives permettent de spécifier très simplement des opérations sur les arbres.
Par exemple la fonction TestArbre donnée dans le fichier patron détermine si tous les noeuds
de l’arbre sont valide par un parcours récursif de l’arbre.
1- Hauteur d’un arbre
La hauteur d’un arbre est définie comme la longueur du plus long chemin pour aller des feuilles
jusqu’à la racine. Une feuille a une hauteur de 0.
Considérons le sous-arbre qui a pour racine Ancetre4 sur la Figure 1. Il y a 2 chemins possibles
pour aller des feuilles à la racine : (Crocodile, Ancetre4 ) et (Kiwi, Ancetre4 ). Ces deux chemins ont
une longueur de 1, ainsi ce sous-arbre a pour hauteur 1.
Considérons maintenant le sous-arbre qui a pour racine Ancetre3. Il y a deux façons d’arriver
à Ancetre3 : soit on vient de Ancetre4, soit on vient de la feuille Cobaye. La hauteur du sous-arbre
qui a pour racine Ancetre4 est 1. La hauteur de la feuille Cobaye est 0. Donc le plus long chemin
pour arriver à Ancetre3 passe forcément par Ancetre4, et sa longueur est 1 + 1 = 2. La hauteur du
sous-arbre ayant pour racine Ancetre3 est donc 2.
a- En suivant le même raisonnement, déterminez les hauteurs des sous-arbres ayant pour
racine Ancetre2, Ancetre1, ou Ancetre0. Proposez une formalisation mathématique de votre
calcul à chaque étape. Identifiez le cas général, le ou les cas particulier(s).
b- Ecrivez une fonction Hauteur(A) qui renvoie la hauteur d’un arbre A.
UPMC - Licence Biologie Mathématiques
3
feuille de Projet Phylogénie
IAP 2013-2014
h=3
AC0
h=2
AC0
E1
AC1
AC1
E2
AC2
AC2
E1
E3
E2
E3
E4
E4
FIGURE 2 - Arbres phylogénétiques construits à partir de 4 espèces actuelles : E1, E2, E3 et E4.
Les espèces ancestrales sont dénommées AC0 (racine), AC1 et AC2. Les deux arbres représentent
deux cas extrêmes, correspondant à une hauteur maximale (à gauche) et minimale (à droite).
2- Nombre total de noeuds
a- En vous inspirant du calcul précédent, proposer une manière récursive de calculer le nombre
total de noeuds d’un arbre.
b- Ecrivez une fonction NumNoeuds(A) qui renvoie le nombre total de noeuds d’un arbre A.
c- La Figure 2 représente deux cas extrêmes : (à gauche) arbre allongé ayant une hauteur
maximale, respectivement au nombre de feuilles, (à droite) arbre étalé ayant une hauteur
minimale, respectivement au nombre de feuilles. On rappelle que chaque noeud d’un arbre
phylogénétique est soit une feuille (pas d’enfant) soit un parent de deux enfants (événement
de spéciation).
• Quelle hauteur maximale peut avoir un arbre construit à partir de n espèces actuelles ?
• Etant donné un nombre n de feuilles (espèces actuelles), par combien d’ancêtres communs, au plus, sont-elles reliées ? Quelle est la hauteur correspondante ?
3- Affichage
Ecrivez une fonction récursive AfficherArbre(A, marge = 0, mcar =’-’) qui, étant donnés une
marge initiale marge et un caractère délimiteur mcar, affiche l’arbre A de telle façon que les
noeuds apparaissant au même niveau de l’arbre sont alignés. La figure ci-dessous donne un exemple
d’affichage avec les valeurs par défaut des arguments marge et mcar.
UPMC - Licence Biologie Mathématiques
4
feuille de Projet Phylogénie
IAP 2013-2014
4- Nombre d’arbres possibles
Etant donné un ensemble d’espèce actuelles données, on cherche à déterminer le nombre d’arbres
phylogénétiques que l’on peut construire, ayant pour feuilles ces espèces.
Le nombre d’arbres phylogénétiques que l’on peut construire à partir de n espèces actuelles
est :
(2n − 3)!
Cn = n−2
(1)
2
(n − 2)!
Cette formule satisfait la relation de récurrence suivante :
C1
Cn
=
=
1
(2n − 3)Cn−1
(2)
(3)
a- Vérifiez cette relation de récurrence en considérant les différentes possibilités pour l’ajout
d’une espèce supplémentaire à un arbre déjà construit.
b- En utilisant cette suite, écrivez une fonction récursive NbArbresPossibles(NFeuilles) qui
renvoie le nombres d’arbres phylogénétiques que l’on peut construire avec NFeuilles feuilles.
c- Calculer le nombre d’arbres possibles avec 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 feuilles. Qu’en déduisezvous ?
Exercice - 4 Inférence de phylogénies
Dans cette partie, nous allons aborder le problème de l’identification de liens de parenté entre
espèces et de la reconstruction d’arbres phylogénétiques. Considérant l’explosion combinatoire que
représente la reconstruction d’arbres à partir d’un ensemble d’espèces actuelles, vous allez devoir
définir un critère d’évaluation de la vraisemblance des arbres que vous allez construire, afin de
choisir le meilleur arbre.
1- Proximité de deux espèces
Etant données deux espèces (ancestrales ou actuelles), on peut apprécier leur ressemblance
en se basant sur leurs caractères morphologiques ou anatomiques. Typiquement, plus les espèces
partagent de caractères communs, plus elles sont proches dans le processus d’évolution. Si on
reprend l’exemple de la Figure 1, le kiwi et le crocodile possèdent tous deux des mâchoires, des
doigts, un amnios et un gésier. Ils sont donc très proches dans l’arbre et aucune autre espèce ne
les sépare. Par contre, entre le crocodile et le cobaye, on note une différence : le cobaye ne possède
pas de gésier mais un placenta. Ainsi, le cobaye est placé plus loin du crocodile que le kiwi dans
l’arbre, et il ne descend pas directement du même ancrêtre commun.
Ainsi, on peut calculer un score de similarité pour rendre compte de la parenté entre deux
espèce. Le score de similarité de la paire (Crocodile, Kiwi) est maximal et est égal au nombre
d’attributs considérés, soit 5.
a- Quel est le score de similarité de la paire (Crocodile, Cobaye) ?
b- Ecrivez une fonction CalculeScorePaire(att1,att2) qui calcule et renvoie le score de similarité
entre deux listes d’attributs.
2- Attributs de l’ancêtre commun à deux espèces
Au fur et à mesure de la reconstruction d’un arbre phylogénétique, les espèces actuelles vont être
reliées par l’introduction d’espèces ancestrales. Quels sont les atributs de ces espèces ancestrales ?
Pour répondre à cette question, il faut considérer trois éléments essentiels :
— Toute nouvelle caractéristique morphologique ou anatomique apparaissant dans le processus d’évolution est définitivement acquise
— L’ancêtre commun à deux espèces représente une forme de consensus entre les deux
espèces
UPMC - Licence Biologie Mathématiques
5
feuille de Projet Phylogénie
IAP 2013-2014
— L’ancêtre commun à deux espèces les précède dans le processus d’évolution, donc dans
le temps.
Si on prend de nouveau l’exemple du crocodile et du kiwi, qui possèdent exactement les mêmes
attributs ([1,1,1,0,1]), on peut en déduire de manière triviale que leur ancêtre commun Ancetre4
possède également les mêmes attributs ([1,1,1,0,1]). Par contre, l’ancêtre commun Ancetre3 doit
représenter un consensus entre Ancetre4, qui possède un gésier et pas de placenta, et le cobaye, qui
possède un placenta et pas de gésier. Etant donné que tout caractère nouveau est définitvement
aqcuis, il faut considérer que ni le gésier, ni le placenta ne sont présents chez Ancetre3. Ainsi la
liste d’attributs d’Ancetre3 est [1,1,1,0,0].
a- Remplir la table de vérité suivante (V : vrai, F : faux) :
A B A et (non B) A ou (non B) (non A) ou B (non A) et (non B)
V F
V F
F V
F F
b- Soit un attribut qui prend la valeur booléenne B1 dans une espèce E1 et B2 dans une
espèce E2. Exprimez la valeur de l’attribut dans l’ancêtre commun aux deux espèces, sous
forme d’une expression booléenne.
c- Ecrivez une fonction FusionneCaracteres(att1,att2) qui renvoie la liste d’attributs de l’ancêtre commun aux espèces ayant pour attributs att1 et att2.
3- Score d’un arbre
Le score total d’un arbre peut être calculé en ajoutant les scores de similarité entre chaque
paire d’enfants. La fonction CalculeScoreArbreSimple(A) définie dans le fichier miniProjet_phylo.py
permet de faire ce calcul de manière récursive.
a- Identifiez, dans le code de la fonction, les instructions qui se réfèrent au cas général et au(x)
cas particulier(s).
b- En prenant l’exemple de l’arbre représenté sur la figure 1, schématisez les différentes étapes
du calcul du score total de cet arbre par la fonction CalculeScoreArbreSimple(A).
c- De quoi faut-il s’assurer avant de faire le calcul de score de similarité entre les enfants de
A ? Introduisez un test qui affiche une erreur si l’arbre est mal construit.
4- Reconstruction d’arbre par une heuristique “Neighbor-Joining”
Maintenant que vous avez défini une fonction de score, vous avez un moyen d’évaluer la vraisemblance d’un arbre. Pour trouver le meilleur arbre, étant donné un ensemble d’espèces actuelles,
la première idée qui vient à l’esprit est de construire tous les arbres possibles et de calculer le score
associé à chacun. Le meilleur arbre est celui qui a le meilleur score.
Cependant, au vu de l’explosion combinatoire que représente la construction de tous les arbres
possibles (cf ex. 4-4), il peut être avantageux d’adopter une stratégie heuristique, qui permette
d’éviter la construction de tous les arbres.
On a vu que, typiquement, si deux espèces ont un score de similarité très élevé, alors elles
sont probablement très proches dans le processus d’évolution. On peut appliquer ce principe à
la construction de l’arbre : étant donné un ensemble de n espèces actuelles, on cherche les deux
espèces les plus proches et on les relie par un ancêtre commun direct.
UPMC - Licence Biologie Mathématiques
6
feuille de Projet Phylogénie
IAP 2013-2014
E1 E2 E3 E4 E5
AC25
E2
E1 E3 E4
E5
On obtient ainsi n − 2 espèces actuelles et un arbre avec pour racine une espèce ancestrale et
deux feuilles (espèces actuelles). A l’étape suivante, on procède de la même façon : on cherche,
parmi les n − 2 espèces actuelles seules et l’espèce ancestrale racine, les 2 espèces les plus proches
et de nouveau on les relie par un ancêtre commun.
a- Ecrivez un algorithme en pseudo-code qui permette de mettre en place cette stratégie de
“Neighbor-Joining”. Vous privilégierez le recours à des fonctions.
b- Implémenter l’algorithme, en utilisant des fonctions que vous avez définies précédemment.
Exercice - 5 Application à des données biologiques
On a étudié les caractéristiques morphologiques et anatomiques de 8 espèces. On souhaite
établir leurs liens de parenté, et reconstruire l’arbre phylogénétique le plus plausible.
1- Tableau d’attributs
Le fichier tableau_carac_diverse.csv contient les informations relatives aux espèces étudiées. La
première ligne indique les caractéristiques morphologiques et anatomiques considérées. Ensuite, sur
chaque ligne, est indiqué le nom d’une espèce, et si chaque caractéristique est présente ou absente
chez cette espèce.
a- Repérez le caractère séparateur dans ce fichier.
b- Ecrivez une fonction LitFichierAttributs(nomFichier,sep), qui lit les informations contenues
dans un fichier nomFichier, ayant pour caractère de séparation sep. On considère que le fichier
est formatté de la même façon que tableau_carac_diverse.csv. La fonction renvoie un doublet
dont le premier élément est la liste des caractéristiques considérées, et le deuxième élément
est un tableau à deux dimensions où chaque ligne contient le nom de l’espèce et la liste de ses
attributs. On rappelle que chaque attribut a une valeur booléenne (Vrai/Faux ou 0/1).
2- Tableau de distances
Pour se donner une première idée des liens de parenté entre les espèces, il est utile de construire
une matrice des distances entre espèces.
a- Proposez un moyen de transformer les scores de similarités calculés par la fonction CalculeScorePaire(att1,att2) en distances.
b- Ecrivez une fonction CalculeDistancePaire(att1,att2) qui calcule et renvoie la distance entre
deux listes d’attributs.
c- Ecrivez une fonction CalculeTableauDist(tableauAtt) qui calcule les distances entre toutes
les paires d’un ensemble n d’espèces, ayant pour tableau d’attributs tableauAtt.
3- Reconstruction de l’arbre phylogénétique
Reconstruisez l’arbre phylogénétique des ces espèces en utilisant l’heuristique de “NeighborJoining”. Comment s’assurer que la solution trouvée est la plus vraisemblable ?
UPMC - Licence Biologie Mathématiques
7
feuille de Projet Phylogénie
IAP 2013-2014
4- Utilisation de données moléculaires
Pour comparer des espèces, des données moléculaires peuvent être utilisées, en complément
ou remplacement des caractéristiques morphologiques ou anatomiques. Typiquement ces données
moléculaires sont des séquences d’acides aminés de protéines homologues. Ces séquences sont dans
un premier temps alignées, c’est-à-dire qu’on détermine quels acides aminés se correspondent ou
sont équivalents dans les séquences. Puis, pour chaque position de l’alignement, on considère un
appariement si les acides aminés des séquences sont strictement identiques, un misappariement
sinon. La distance entre deux séquences est évaluée comme le nombre de misappariements.
Dans le fichier tableau_sequence_diverse.csv se trouvent les séquences alignées pour les espèces.
Pour chaque ligne le nom de l’espèce est indiquée, suivie de la séquence alignée de la protéine
homologue.
a- Adaptez la fonction CalculeScorePaire en une fonction CalculeScorePaireSeq pour calculer
le score de similarité entre deux séquences.
b- De la même façon, écrivez une fonction qui calcule le tableau de distance entre toutes les
paires en utilisant la similarité entre les séquences.
c- (bonus) Adaptez l’heuristique de "Neighbor-Joining" pour prendre en compte des séquences
d’acide aminés. Le problème se pose maintenant de décider comment représenter les séquences
ancestrales après chaque fusion de deux espèces. Proposez une méthode pour calculer la séquence ancestrale puis écrivez la fonction correspondante.
UPMC - Licence Biologie Mathématiques
8