Алгоритм для нахождения изоморфного множества подстановок
У меня есть массив множеств перестановок, и я хочу удалить изоморфные перестановки.
У нас есть S
множества перестановок, где каждый набор содержит подстановки K
, и каждая перестановка представляется как и массив элементов N
. Я сохраняю его как массив int pset[S][K][N]
, где S
, K
и N
фиксированы, а N больше K.
Два набора перестановок A
и B
являются изоморфными, если существует перестановка P
, которая преобразует элементы из A
в B
(например, если A
является элементом множества A
, то P(a)
является элементом множества B
). В этом случае мы можем сказать, что P
делает A
и B
изоморфным.
Мой текущий алгоритм:
- Выберем все пары
s1 = pset[i]
и s2 = pset[j]
, такие, что i < j
- Каждый элемент из выбранных множеств (
s1
и s2
) числится от 1
до K
. Это означает, что каждый элемент может быть представлен как s1[i]
или s2[i]
, где 0 < i < K+1
- Для каждой подстановки
T
элементов K
мы делаем следующее:
- Найдите перестановку
R
, такую, что R(s1[1]) = s2[1]
- Проверьте, является ли
R
перестановка, которая делает изоляцию s1
и T(s2)
, где T(s2)
является перестановкой элементов (перестановок) множества s2
, поэтому в основном мы просто проверяем, если R(s1[i]) = s2[T[i]]
, где 0 < i < K+1
- Если нет, то переходим к следующей перестановке
T
.
Эти алгоритмы работают очень медленно: O(S^2)
для первого шага, O(K!)
, чтобы перебрать каждую перестановку T
, O(N^2)
, чтобы найти R
и O(K*N)
, чтобы проверить, что R
является перестановкой, которая делает s1
и s2
изоморфной - так что это O(S^2 * K! * N^2)
.
Вопрос: Можем ли мы сделать это быстрее?
Ответы
Ответ 1
Для этого есть очень простое решение: транспонирование.
Если два множества изоморфны, это означает, что существует взаимно однозначное отображение, где множество всех чисел в индексе i
в наборе S1
равно множеству всех чисел в некотором индексе k
в наборе S2
. Моя гипотеза состоит в том, что никакие два неизоморфных множества не обладают этим свойством.
(1) Пример Жана Логейта:
0: [[1,2,3],[3,2,1]]
1: [[2,3,1],[1,3,2]]
2: [[1,2,3],[2,3,1]]
3: [[3,2,1],[1,2,3]]
Perform ONE pass:
Transpose, O(n):
0: [[1,3],[2,2],[3,1]]
Sort both in and between groups, O(something log something):
0: [[1,3],[1,3],[2,2]]
Hash:
"131322" -> 0
...
"121233" -> 1
"121323" -> 2
"131322" -> already hashed.
0 and 3 are isomorphic.
(2) встречный пример vsoftco в своем комментарии к Жану Логейту:
A = [ [0, 1, 2], [2, 0, 1] ]
B = [ [1, 0, 2], [0, 2, 1] ]
"010212" -> A
"010212" -> already hashed.
A and B are isomorphic.
Вы можете превратить каждый набор в транспонированную сортированную строку или хеш или любой другой сжатый объект для сравнения по линейному времени. Заметим, что этот алгоритм рассматривает все три набора A
, B
и C
как изоморфные, даже если один p
преобразует A
в B
, а другой p
преобразует A
в C
. Ясно, что в этом случае существует p
для преобразования любого из этих трех множеств в другое, поскольку все, что мы делаем, перемещает каждый i
в одном наборе в конкретный k
в другой. Если, как вы заявили, ваша цель - "удалить изоморфные перестановки", вы все равно получите список удаляемых наборов.
Пояснение:
Предположим, что наряду с нашим отсортированным хешем мы сохранили запись о том, из какой перестановки вышла каждая из i
. Пример противодействия vsoftco:
010212 // hash for A and B
100110 // origin permutation, set A
100110 // origin permutation, set B
Чтобы подтвердить изоморфизм, нам нужно показать, что i
, сгруппированные по каждому индексу из первого набора, переместились в некоторый индекс во втором наборе, причем этот индекс не имеет значения. Сортировка групп i
не отменяет решение, а служит для подтверждения перемещения/перестановки между наборами.
Теперь по определению каждое число в хеше и каждое число в каждой группе в хеше представлено в перестановке начала ровно один раз для каждого набора. Однако мы решили упорядочить числа в каждой группе i
в хэше, мы гарантируем, что каждое число в этой группе представляет собой другую перестановку в множестве; и в тот момент, когда мы теоретически присваиваем это число, мы гарантируем, что он "зарезервирован" только для этой перестановки и индекса. Для данного числа, скажем 2
, в двух хэшах нам гарантируется, что он исходит из одного индекса и перестановки в наборе A
, а во втором хеш соответствует один индекс и перестановка в наборе B
. Это все, что нам действительно нужно показать, - что число в одном индексе для каждой перестановки в одном наборе (группа различных i
's) попадает в один индекс только в другом наборе (группа различных k
') с). Какая перестановка и индекс, к которому принадлежит номер, не имеют значения.
Помните, что любое множество S2
, изоморфное множеству S1
, может быть получено из S1
с использованием одной функции перестановки или различных комбинаций различных функций перестановок, применяемых к членам S1
. То, что на самом деле представляет сортировка или переупорядочение наших чисел и групп, - это перестановка, которую мы выбираем как решение изоморфизма, а не фактическое присвоение того числа, из которого пришел индекс и перестановка. Здесь снова встречный пример vsoftco, на этот раз мы добавим начальные индексы наших хэшей:
110022 // origin index set A
001122 // origin index set B
Поэтому наш permutation, решение для изоморфизма:
![enter image description here]()
Или, чтобы:
![enter image description here]()
(Обратите внимание, что в примере Жана Лойарта существует более одного решения изоморфизма.)
Ответ 2
Вы можете сортировать и сравнивать:
// 1 - sort each set of permutation
for i = 0 to S-1
sort(pset[i])
// 2 - sort the array of permutations itself
sort(pset)
// 3 - compare
for i = 1 to S-1 {
if(areEqual(pset[i], pset[i-1]))
// pset[i] and pset[i-1] are isomorphic
}
Конкретный пример:
0: [[1,2,3],[3,2,1]]
1: [[2,3,1],[1,3,2]]
2: [[1,2,3],[2,3,1]]
3: [[3,2,1],[1,2,3]]
После 1:
0: [[1,2,3],[3,2,1]]
1: [[1,3,2],[2,3,1]] // order changed
2: [[1,2,3],[2,3,1]]
3: [[1,2,3],[3,2,1]] // order changed
После 2:
2: [[1,2,3],[2,3,1]]
0: [[1,2,3],[3,2,1]]
3: [[1,2,3],[3,2,1]]
1: [[1,3,2],[2,3,1]]
После 3:
(2, 0) not isomorphic
(0, 3) isomorphic
(3, 1) not isomorphic
Как насчет сложности?
- 1
O(S * (K * N) * log(K * N))
- 2
O(S * K * N * log(S * K * N))
- 3
O(S * K * N)
Таким образом, общая сложность O(S * K * N log(S * K * N))
Ответ 3
Возьмите a0
в A
. Затем найдите его обратным (быстрым, O(N)
), назовите его a0inv
. Затем выберите i
в B
и определите P_i = b_i * ainv
и убедитесь, что P_i * a
генерирует B
при изменении A
над A
. Сделайте это для каждого i
в B. Если вы не найдете никакого i
, для которого выполняется соотношение, то множества не изоморфны. Если вы найдете такой i
, то множества изоморфны. Время выполнения O(K^2)
для каждой пары проверяемых наборов, и вам нужно будет проверить набор O(S^2)
, поэтому вы получите O(S^2 * K^2 * N)
.
PS: Я предположил, что под "отображением А в В" вы подразумеваете отображение под композицией перестановок, поэтому P(a)
на самом деле является перестановкой P
, состоящей из перестановки A
, и я использовал тот факт, что если P
является перестановкой, то должно существовать a i
, для которого Pa = b_i
для некоторого A
.
EDIT Я решил отменить свой ответ, поскольку я не уверен, что предыдущий (@Jean Logeart) на основе поиска правильный. Если да, я с удовольствием удалю мое, потому что он работает хуже, но я думаю, что у меня есть контрпример, см. Комментарии ниже ответа Жана.
Ответ 4
Предположим, что два элемента s1, s2\in S изоморфны. Тогда, если p1 и p2 являются перестановками, то s1 изоморфно s2, если p1 (s1) изоморфно p2 (s2), где pi (si) - множество подстановок, полученных применением pi к каждому элементу из si.
Для каждого я из 1... s и j в 1... k, выберем j-й элемент si и найдем перестановку, которая изменит ее на единицу. Примените его ко всем элементам si. Перемешиваем каждую из k перестановок на число, получая k чисел, для любого выбора я и j по стоимости nk.
Сравнение хешированных множеств для двух разных значений я и j равно k ^ 2 < пк. Таким образом, вы можете найти набор совпадений кандидатов по цене s ^ 2 k ^ 3 n. Если фактическое количество совпадений невелико, общая сложность намного ниже того, что вы указали в своем вопросе.
Ответ 5
Чтобы проверить, являются ли два набора S₁ и S₂ изоморфными, вы можете сделать гораздо более короткий поиск.
Если они изоморфны, то существует перестановка t, которая отображает каждый элемент S₁ в элемент S₂; для поиска t вы можете просто выбрать любой фиксированный элемент p S₁ и рассмотреть перестановки
t₁ = (1/p) q₁
t₂ = (1/p) q₂
t₃ = (1/p) q₃
...
для всех элементов q S₂. Ибо, если существует допустимый t, то он должен отображать элемент p в элемент S₂, поэтому только перестановки отображения p к элементу S₂ являются возможными кандидатами.
Кроме того, если у вас есть кандидат t, чтобы проверить, равны ли два набора перестановок S₁t и S₂, вы можете использовать хэш, вычисленный как x -или хэш-кода для каждого элемента, выполняя полную проверку всех перестановок, только если хеш соответствует.