2010-11-04 4 views
5

j'ai une sorte de structure arborescente un niveau que:Combinatoire en Python

alt text

Où p sont des nœuds parents, c sont des nœuds enfants et b sont hypothétiques branches.

Je veux trouver toutes les combinaisons de branches sous la contrainte que seul un parent branche peut seulement un nœud enfant, et deux branches ne peut pas partager des parents et/ou enfants.

E.g. si combo est l'ensemble des combinaisons:

combo[0] = [b[0], b[3]] 
combo[1] = [b[0], b[4]] 
combo[2] = [b[1], b[4]] 
combo[3] = [b[2], b[3]] 

Je pense que ce tous. =)

Comment cela peut-il être obtenu automatiquement en Python pour des arbres arbitraires de ces structures, c'est-à-dire que le nombre de p: s, c: s et b: s est arbitraire.

EDIT:

Il n'est pas un arbre mais une bipartitedirected acyclic graph

+0

Votre image suggère qu'il y a des branches disponibles de chaque parent à chaque enfant. Est-ce que vous supposez cela? – dhill

+0

Avez-vous déjà une structure de données pour représenter cela? –

+2

@dhill - Est-ce que c'est? Le noeud parent p1 ne se connecte pas à l'enfant c0. – Theodor

Répondre

4

Voici une façon de le faire. Il y a beaucoup de micro-optimisations qui pourraient être faites mais leur efficacité dépendrait des tailles impliquées.

import collections as co 
import itertools as it 

def unique(list_): 
    return len(set(list_)) == len(list_) 

def get_combos(branches): 
    by_parent = co.defaultdict(list) 

    for branch in branches: 
     by_parent[branch.p].append(branch) 

    combos = it.product(*by_parent.values()) 

    return it.ifilter(lambda x: unique([b.c for b in x]), combos) 

Je suis sûr que ce soit au moins frapper la complexité optimale car je ne vois pas un moyen d'éviter de regarder toutes les combinaisons qui est unique par le parent.

+0

Je pense que vous vouliez avoir l'argument pour que get_combos soit une branche, sinon pour une branche dans une branche, une exception sera levée. –

+0

@Philip Bon à regarder. Fixé. – aaronasterling

+0

Merci beaucoup, bonne solution! – Theodor

3

Regardez itertools générateurs combinatoires:

  • produit()
  • permutations()
  • combinaisons ()
  • combinations_with_replacement()

On dirait que vous pouvez écrire un itérateur pour réaliser ce que vous voulez.