Condition ne fonctionne pas [Résolu]

Messages postés
1
Date d'inscription
mercredi 12 juin 2019
Statut
Membre
Dernière intervention
12 juin 2019
-
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 ?
Afficher la suite 

1 réponse

Messages postés
29016
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
12 octobre 2019
6669
0
Merci
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
Commenter la réponse de mamiemando