Parcourir un graphe dans les deux sens
Bonjour à tous,
Je suis en train de créer un algorithme qui me permettrai de me trouver toutes les chaines d'interactions de taille 4 dans cet arbre en prenant en compte le fait que nous pouvons remonter dans l'arbre (les interactions sont à double sens) (et on ne peut pas retrouver deux fois le même chiffre dans une chaîne).
Code:
1 2 3 4 5 6 7 8 9 10 11
|
1
- -
- -
6 4
- -
- -
- 9
- -
- -
33 66 |
J'ai réussi a générer les chaines de tailles 4 (voici ce que me trouve actuellement mon algorithme)
1 6 9 66
1 6 9 4
1 6 9 33
1 4 9 6
1 4 9 66
1 4 9 33
4 1 6 9
4 9 6 1
6 1 4 9
6 9 4 1
9 6 1 4
9 4 1 6
33 9 6 1
33 9 4 1
66 9 6 1
66 9 4 1
Cependant il me faudrait aussi les "chaines intermédiaires", c'est a dire les chaines qui sont "bloquées" avant d'atteindre la taille de 4, par exemple :
4-9-33
6-9-33
9-33
9-66
66-9-33
33-9-66
6-9-66
ect...
ça ne doit pas être grand chose à modifier/rajouter, j'ai fait des recherches sur de potentielles fonctions (intertools notamment) permettant cela mais je ne trouve rien qui résolve mon problème...
Voici le fichier sur lequel je travaille:
1 4
1 6
4 9
6 9
9 33
9 66
4 1
6 1
9 4
9 6
33 9
66 9
Voici mon algorithme actuel (je travaille sur des protéines, représentées ici par les chiffres):
Code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
import sys
sys.setrecursionlimit(1000000)
from collections import defaultdict
dd = defaultdict(set)
with open ("C:/Users/lveillat/Desktop/Données stage/Fichiers tests/testchaines3.txt","r") as f1:
for ligne in f1:
lp = ligne.rstrip('\n').split(" ")
prot1 = lp[0] #je sélectionne la première protéine de chaques interactions
prot2 = lp[1] #je sélectionne la seconde protéine de chaques interactions
dd[prot1].add(prot2) #Je crée mon dictionnaire avec en clé la première prot de l'interaction et en valeurs l'ensembles des prots avec qui elle peut interagir
print(dd)
def chain(maillon, pathway, limite=4): #Je définis une fonction chain(maillon, chaine d'interaction, limite de taille de la chaine)
next_ = maillon.get(pathway[-1], None) #next_ = On rajoute un maillon à la chaine existante en fonction de la dernière protéine du pathway
if next_ is None or len(pathway) >= limite : #Si il n'y a pas de protéine trouvée interagissant avec la dernière protéine du pathway, ou si la taille dépasse la limite alors on passe a la chaine suivante
yield pathway #yield est pratique quand on sait que la fonction va retourner de nombreuses valeurs qu?on ne souhaite lire qu?une seule fois (c'est notre cas ici), permet d'économiser de la mémoire.
else: #Si on trouve encore des protéines interagissant avec la dernière protéine du pathway et si la taille limite n'est pas atteinte,
for m in next_: # pour une interaction dans l'ensemble des interactions possibles de pathway[-1]
if m not in pathway:
yield from chain(maillon, pathway + [m]) #On rajoute une autre prot à la chaine uniquement si la protéine que l'on rajoute n'est pas déjà apparue dans la chaine
for k in dd: # Pour chaques prot du dico
for z in chain(dd, pathway = [k]): #Pour chaques chaines
print (' '.join(z)) |
et voici ma sortie actuelle :
defaultdict(<class 'set'>, {'1': {'6', '4'}, '4': {'1', '9'}, '6': {'1', '9'}, '9': {'6', '66', '4', '33'}, '33': {'9'}, '66': {'9'}})
1 6 9 66
1 6 9 4
1 6 9 33
1 4 9 6
1 4 9 66
1 4 9 33
4 1 6 9
4 9 6 1
6 1 4 9
6 9 4 1
9 6 1 4
9 4 1 6
33 9 6 1
33 9 4 1
66 9 6 1
66 9 4 1
Merci de votre aide