2017-01-16 4 views
1

Меня интересует только Python, но также будет оценено общее решение. У меня есть четное число узлов (скажем, 12 для конкретного примера):Поиск комбинаций пар (соединений)

[ 'a1', 'a2', 'a3', 'b1', 'b2', 'b3', «c1 ',' c2 ',' c3 ',' d1 ',' d2 ',' d3 ']

Каждый узел должен быть подключен к другому узлу, образуя 6 соединений (пары). Мне нужно выяснить, как найти все возможные комбинации соединений. Кроме того, 'a1'-'a2' следует рассматривать так же, как 'a2'-'a1'

Некоторые мысли:

  • я могу получить список возможных itertools.combinations(lst, 2), но узлы не подлежит повторному использованию. Скажем, соединение 'a1'<->'a2' должно устранить 'a1'<->'a3' из доступных вариантов, поскольку 'a1' уже используется.

  • Я понятия не имею, если поиск даже применимо, как кажется, есть несколько проблем:

    • там, кажется, нет (легкий, дешевый) способ отслеживать посещенные состояния
    • решение всегда будет на день (нужно перемещаться по дереву всех вплоть до завершения всех соединений)
+0

Вы хотите найти все возможные конфигурации соединений, не так ли? То есть список [[1,2], [3,4], ... [11,12]] представляет собой одну конфигурацию, и вы хотите найти все возможные такие списки. – jf328

+1

Является ли это направленным или неориентированным графом? Например, a1-a2 такой же, как a2-a1? –

+0

Да, это то, что я ищу, и a1-a2 такой же, как a2-a1 – dccharacter

ответ

3

Рекурсивное решение проблемы:

def findPairs(l): 
    # recursion anchor, basic case: 
    # when we have 2 nodes only one pair is possible 
    if len(l) == 2: 
     yield [tuple(l)] 
    else: 
     # Pair the first node with all the others 
     for i in range(1, len(l)): 
      # Current pair 
      pair1 = [(l[0], l[i])] 
      # Combine it with all pairs among the remaining nodes 
      remaining = l[1:i] + l[i+1:] 
      for otherPairs in findPairs(remaining): 
       yield pair1 + otherPairs 

Число всех решений может быть вычислен соответственно:

def N(n): 
    if n == 2: 
     return 1 
    return (n-1) * N(n-2) 

Обратите внимание, что я не проверял на n % 2 == 0.

Также для n==len(l)==12 вы получите 10395 возможных комбинаций, которые вполне выполнимы. Но этот код, будучи коротким и читаемым, снова и снова переводит и регенерирует списки и кортежи, что замедляет работу.
Посмотрите, достаточно ли это для вас, иначе нам придется его подстроить.

+0

Странно, я пытаюсь проверить его, и он работает правильно, если я распечатываю список (findPairs (l)), но если я распечатаю findPairs (l) .next(), он дает только самую первую конфигурацию :-( – dccharacter

+0

Это потому, что он возвращает [generator] (https://wiki.python.org/moin/Generators). 'List (findPairs (l))' вероятно, что вам нужно, если вы не пытаетесь найти все комбинации для список с 18 узлами, которые занимают очень много времени. Вот для чего нужны генераторы. – swenzel

+0

Да, я знаю, что это генератор. Поэтому функция next() должна извлекать следующий элемент из генератора. И это не так. возвращает мне самую первую комбинацию, как будто что-то сбрасывает ее. – dccharacter

1

Я думаю, вам просто нужно использовать р ermutations и take adjacent pairs, затем удалить любые обращенные дубликаты заказа:

nodes = 'A1 A2 B1 B2 C1 C2'.split() 
perms = set() 
for perm in itertools.permutations(nodes): 
    p = tuple(sorted(
     [tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)])) 
    perms.add(p) 

for perm in sorted(perms): 
    print(perm) 

Так как же это работает?

Нам нужно перебрать каждую перестановку узлов:

for perm in itertools.permutations(nodes): 

Затем создают пары из соседних узлов в перестановке:

[tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)] 

Это делается с помощью взятия двух соседних узлов и сортировок их так, чтобы мы могли искать дубликатов позже:

tuple(sorted(perm[i:i + 2])) 

, а затем создайте tuple, чтобы у нас было что-то immutable, чтобы разрешить индексирование.Затем возьмите все пары для одной перестановки и выполняет те же sort и преобразование в tuple для всей перестановки:

p = tuple(sorted(
    [tuple(sorted(perm[i:i + 2])) for i in range(0, len(perm), 2)])) 

Затем добавить перестановку в set, которая удаляет дубликаты:

perms.add(p) 

И распечатать результаты:

for perm in sorted(perms): 
    print(perm) 
+1

Но у вас будут дубликаты. «A1A2, B1B2» совпадает с «A2A1, B2B1». Для 4 узлов единственными являются только «12, 34», «13», «24», «14, 23». Принимая всю перестановку, фильтр кажется слишком медленным. (Но я даже не знаю, как это сделать) – jf328

+0

@ jf328, спасибо, обновлено –

+0

Это работает, но это слишком медленно :-) Он также довольно долго висит после каждых 944 попыток. Наверное, это происходит, когда он проходит через пары «обратного». – dccharacter

 Смежные вопросы

  • Нет связанных вопросов^_^