Condition ne fonctionne pas

Résolu/Fermé
Amniote Messages postés 1 Date d'inscription mercredi 12 juin 2019 Statut Membre Dernière intervention 12 juin 2019 - Modifié le 17 juil. 2019 à 11:44
mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 - 17 juil. 2019 à 13:26
Bonjour,

J'ai un fichier
test
suivant :

1 4
1 6
4 9
6 9
9 33
9 66
4 1
6 1
9 4
9 6
33 9
66 9


J'ai le code suivant :

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 de la chaine
 
 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 la sortie suivante :

defaultdict(<class 'set'>, {'1': {'6', '4'}, '4': {'9', '1'}, '6': {'9', '1'}, '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 9 6 1
4 1 6 9
6 9 4 1
6 1 4 9
9 6 1 4
9 4 1 6
33 9 6 1
33 9 4 1
66 9 6 1
66 9 4 1


Ce programme doit me sortir toutes les chaines d'interactions possibles composées de 4 chiffres (1 interagit avec 4 et avec 6 par exemple). Donc le programme fonctionne bien comme vous pouvez le voir, à un détail près : l'algorithme ne me donne pas les chaines d'interactions intermédiaires. Par exemple je devrais trouver la chaîne suivante :
66 9 33
ou celle-ci
33 9 4
...

Avez-vous une idée de ce qui ne fonctionne pas ?

1 réponse

mamiemando Messages postés 33079 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 23 avril 2024 7 749
Modifié le 17 juil. 2019 à 13:26
Bonjour,

Juste pour comprendre, si ton fichier contient disons :

1 2
2 1


... est-ce qu'on est sensé retourner toutes les chaînes :

1 2
1 2 1
1 2 1 2
...


Est-ce pour ça que tu as bridé la longueur à 4 ?

Si j'ai bien compris ce que tu veux faire, voilà à quoi pourrait ressembler ton programme (je laisse de côté la partie parsing que tu as déjà faite) :

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

from pprint import pprint

PAIRS = [
    (1, 4),
    (1, 6),
    (4, 9),
    (6, 9),
    (9, 33),
    (9, 66),
    (4, 1),
    (6, 1),
    (9, 4),
    (9, 6),
    (33, 9),
    (66, 9),
]

def make_chains_rec(chain, pairs, limit, res):
    if len(chain) == limit:
        return
    last = chain[-1] if len(chain) >= 1 else None
    for pair in pairs:
        (p1, p2) = pair
        if last is None or p1 == last:
            next_chain = list(chain)
            next_chain.append(p2)
            res.append(next_chain)
            make_chains_rec(next_chain, pairs, limit, res)

def make_chains(pairs, limit = 4):
    chain = list()
    res = list()
    make_chains_rec(chain, pairs, limit, res)
    return res

pprint(make_chains(PAIRS))


Note en particulier que, pour que l'appel récursif marche bien, tu ne peux pas te contenter de passer par référence
chain
, il faut faire un passage par recopie. C'est d'ailleurs peut-être la cause de ton bug (je n'ai pas pris le temps de détailler ton code).

Bonne chance
0