Есть ли алгоритм для генерации всех уникальных круговых перестановок мультисмета?

StackOverflow https://stackoverflow.com/questions/3467914

Вопрос

Я столкнулся с этой проблемой при выполнении некоторого энтузиастового программирования. Проблема может быть выражена следующим образом:

Для многосертного A, пусть p (a) обозначает множество всех возможных перестановов A. p (a), естественно, делится на неразмерные подмыселы, которые являются классами эквивалентности, при этом отношение эквивалентности «может быть связано с круговыми сдвигами». Перечислите все эти классы эквивалентности, создавая ровно один элемент от каждого из них.

Например, рассмотрим многосекретный {0, 1, 1, 2}. Перестановки «0112» и «1201» являются уникальными перестановками, но последние можно найти циркулярно-смещением бывшего и наоборот. Желаемый алгоритм не должен генерировать оба.

Конечно, возможен подход Brute-Force: просто генерируйте перестановки - независимо от циркулярного дублирования - с использованием любого из алгоритмов разрывов мультисетных перестановок и отказаться от дублирования, найденные по сравнению с предыдущими результатами. Однако это имеет тенденцию быть неэффективным на практике. Желаемый алгоритм должен потребовать минимального, если не ноль бухгалтерии.

Любое понимание этой проблемы глубоко ценится.

Это было полезно?

Другие советы

Это немного легче пойти на этот снизу вверх:

Если A содержит только 1 элемент, P (A) также содержит одну перестановку. Легко видеть то же самое произведения, если A только содержит 2 элемента.

Теперь давайте предположим, что у вас уже есть все P (a) для с n элементами, и вы добавляете один элемент. Он может перейти в любую из n пятен в любом из перестановок в p (a).

Я думаю, что эта идея приносит довольно непосредственно на рекурсивный алгоритм на вашем языке выбора, и надеюсь, что мое объяснение было достаточно ясно.

Редактировать: Я знаю, что я вроде проигнорировал тот факт, что может содержать дубликаты элементов, но все еще думая об этой части :)

Точно так же, если вы отсортировали перед началом алгоритма перестановки, я думаю, что это может устранить дубликаты. (Все еще думая об этом тоже)

Для интуитивного понимания проблемы, я думаю, мы можем использовать эту метафору. Визуализируйте часы на стене, но вместо 12 позиций на лице он имеет n где n - количество элементов в вашем наборе.

Затем каждый класс эквивалентности является просто назначением элемента A в положение на лицевой стороне.

После назначения еще одна перестановка из того же класса эквивалентности может быть сгенерирована, просто вращая часы на стене.

Для создания другой не связанной перестановки A нужно иметь элемент пропустить хотя бы один другой элемент.

Теперь алгоритм, как я вижу, было бы начать с назначения, например,, скажем, у нас были четыре элемента A = {A, B, C, D}, и мы присваивали их на 12, 3, 6 и 9 позиций соответственно для визуальных ясность. Тогда наша первая операция будет поменяться и б. Тогда a и c, то a и d, то мы ходили к B и поменяем его с элементом в 3 положении, которое сейчас c.

Делать это, пока мы не достигли d, будут генерировать представитель из всех классов эквивалентности.

Это не заботится о дубликатах, но он должен быть гораздо более эффективным, чем генерировать все перестановки A.

Мысль, которая, на мой взгляд, это то, что для любого набора, который имеет хотя бы один элемент, который появляется только один раз, тогда вы можете поставить этот элемент в первую позицию вашего списка для всех ответов, а затем генерировать все перестановки остальных чисел. Это довольно тривиальное решение, поскольку тот факт, что ваш первый элемент является уникальным, гарантирует, что цикл не содержит эквиваленты цикла. Очевидно, что все решения, которые вы генерируете, должны быть уникальными.

Очевидная проблема заключается в том, что если у вас нет элементов, которые являются одинокими, то это полностью разрушается. Основная причина, по которой я положил это, это потому, что есть несколько других решений, касающихся нет Дубликаты, и я думаю, что это более эффективно, чем они (решает больше случаев) так достойно упоминания. Это также довольно просто с точки зрения понимания того, как он работает и реализует его. Я просто надеюсь, что мои рассуждения звучат. ;-)

Редактировать для дальнейших мыслей:

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

Если вы возьмете один элемент (что мы предполагаем, что теперь повторяется), вы можете посмотреть только на свои перестановки, и какие из них позволили бы повторитению Cycle Shift, как до того, как принесена, что вы можете «заблокировать» на месте без потери общности. Например, если у вас есть 6 элементов, а A появляется дважды в этом наборе, тогда вы можете иметь:

AAXXXX, AXAXXX, AXXAXX, AXXXAX, AXXXXA

Последний из них такой же, как первый (в пределах циклического сдвига), так можно игнорировать, то же самое второе и четвертое. Третий (AXXAXX) может быть зарегистрирован на велосипеде на три, чтобы вернуться к себе, поэтому есть потенциал для циклов. Первые два никогда не могут породить циклы, независимо от того, сколько раз вы их верите их, поэтому вы распространяете оставшиеся элементы, которые вам нужны только гарантируют, что они являются уникальными распределениями, и вы гарантированно получаете уникальные результаты цикла.

Для третьего шаблона, который может цитироваться (Axxaxx), вам нужно будет посмотреть на элемент B и повторить процесс для тех. На этот раз необычно вы не сможете использовать хитрость блокировки первого значения, чтобы сэкономить время.

Я не на 100% уверен, что вы пойдете в полную рабочую программу, но ее вкусные тихии на то, как избежать необходимости грубой силы.

Я предлагаю здесь решение, реализованное в Python

import itertools as it

L = ['a','b','c','d']
B = it.combinations(L,2)
swaplist = [e for e in B]
print 'List of elements to permute:' 
print swaplist
print
unique_necklaces = []
unique_necklaces.append(L)
for pair in swaplist:
    necklace = list(L)
    e1 = pair[0]
    e2 = pair[1]
    indexe1 = L.index(e1)
    indexe2 = L.index(e2)
    #swap
    necklace[indexe1],necklace[indexe2] = necklace[indexe2], necklace[indexe1]
    unique_necklaces.append(necklace)

for n in unique_necklaces:
    # Commented code display the rotation of the elements in each necklace
    print 'Necklaces'
    print n#, [n[-r:]+n[:-r]for r in (1,2,3)]   

Идея состоит в том, чтобы построить разные ожерелья путем перестановок двух элементов. Для списка четырех элементов A, B, C, D Выход ALGO:

['a', 'b', 'c', 'd']
['b', 'a', 'c', 'd']
['c', 'b', 'a', 'd']
['d', 'b', 'c', 'a']
['a', 'c', 'b', 'd']
['a', 'd', 'c', 'b']
['a', 'b', 'd', 'c']
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top