Алгоритм Шрайера — Симса
Алгоритм Шрайера — Симса — алгоритм из области вычислительной теории групп, позволяющий после однократного исполнения за линейное время находить порядок группы, порождённой перестановками, проверять принадлежность элемента такой группе и перечислять её элементы. Алгоритм был предложен Чарльзом Симсом в 1970 году для поиска примитивных групп перестановок[1] и основывается на лемме Шрайера о порождении подгрупп[2]. Представление группы перестановок, которое находит алгоритм, аналогично ступенчатому виду матрицы для её пространства строк[3]. Разработанные Симсом методы лежат в основе большинства современных алгоритмов для работы с группами перестановок[4], модификации алгоритма также используются в современных системах компьютерной алгебры, таких как GAP и Magma[англ.][5]. Одним из наиболее наглядных приложений алгоритма является то, что он может быть использован для решения кубика Рубика[6]. ИсторияОдной из основных задач в теории групп перестановок является поиск групп перестановок заданной степени (то есть минимального числа элементов множества, в группу перестановок которого вкладывается заданная группа перестановок). К 1970 году для степеней от 2 до 11 были найдены все группы перестановок, для степеней от 12 до 15 были найдены все транзитивные группы (то есть подгруппы, действующие на порождающем множестве транзитивно), а для степеней от 16 до 20 были найдены только примитивные группы перестановок[англ.]. Для поиска примитивных групп большей степени Чарльз Симс разработал программу, которая находит порядок и некоторую структуру в группе перестановок, заданной своим порождающим множеством[1]. Оригинальная программа, упомянутая в работе Симса, была написана для IBM 7040[англ.] в Ратгерском университете и поддерживала работу с любыми группами, чья степень не превосходила 50[7]. Точная оценка времени работы алгоритма была впервые проведена Фурстом, Хопкрофтом и Лаксом[англ.] в 1980 году[8]. Время работы было улучшено Джеррумом[англ.] в 1982[9] и Дональдом Кнутом в 1981 году[10]. В 1980 году была разработана эффективная вероятностная версия алгоритма[11]. Различные вариации алгоритма, включая те, которые используют вектор Шрайера[англ.] вместо дерева орбиты, были разобраны Шерешем[нем.] в 2003 году[12][13]. В вычислительной теории групп алгоритмы над группами перестановок — одна из наиболее развитых областей, и даже сегодня большинство из этих алгоритмов основываются на методах, разработанных Симсом[4]. Основная идеяЭффективность вычислений с группой перестановок существенно зависит от того, как она задана в программе[2]. Один из эффективных способов такого задания — выделить ряд её подгрупп и выбрать однозначных представителей смежных классов для каждой подгруппы в этом ряду относительно её предшественника. Предложенный Чарльзом Симсом алгоритм находит ряд подгрупп, в котором каждая следующая группа является стабилизатором предыдущей. Последовательность точек, для которых строятся стабилизаторы, называется базой[англ.], а множество, содержащее образующие элементы для каждой группы в ряду, — сильным порождающим множеством[англ.][2]. Алгоритм строит базу и сильное порождающее множество для подгруппы перестановок, заданной своим порождающим множеством, используя лемму Шрайера для нахождения порождающих множеств. Размер получаемых на промежуточных шагах множеств растёт экспоненциально, поэтому были разработаны вариации алгоритма, уменьшающие количество рассматриваемых порождающих элементов[2]. Описанное выше представление разбивает группу в произведение вложенных в неё подмножеств аналогично тому, как ступенчатое представление разбивает векторное пространство в прямую сумму вложенных в него подпространств[3]. Постановка задачиСимметрической группой называют группу, элементами которой являются перестановки элементов некоторого множества . Обычно в качестве такого множества берётся . В таких обозначениях элементы группы можно рассматривать как отображения , переводящие множество в себя, то есть его автоморфизмы. Групповой операцией в таких обозначениях является композиция перестановок, для перестановок и определяемая как , где для . Соответственно, единичной перестановкой будет перестановка такая, что , а обратная перестановка может быть задана как [14]. Пусть — множество перестановок длины . Порождённой подгруппой множества называют наименьшую по включению подгруппу , которая содержит как подмножество или, что эквивалентно, подгруппу всех элементов , которые могут быть представлены в виде конечного произведения элементов и обратных к ним. Порядком группы перестановок называют число элементов в ней , а её степенью — мощность множества , на котором она действует. В таких обозначениях алгоритм должен уметь[7]:
ПримененияМодификации алгоритма реализованы в двух наиболее популярных специализированных на вычислительной теории групп системах компьютерной алгебры — GAP и Magma[англ.][5]. Инструменты для работы с группами перестановок, включая алгоритмы перечисления смежных классов и алгоритм Шрайера — Симса также представлены в популярных системах более широкого профиля Maple и Mathematica[15]. Изначально алгоритм был разработан для поиска примитивных групп перестановок заданной степени[1], однако впоследствии область его применения многократно выросла — например, с помощью данного алгоритма можно находить решения к заданной конфигурации кубика Рубика, так как его вращения образуют группу[6]. Также алгоритм хорошо показал себя при работе с группами матриц[англ.][16]. АлгоритмФакторизация группыПусть — подгруппа некоторой конечной группы , через обозначим трансверсаль семейства левых смежных классов . Любой элемент может быть единственным образом представлен как , где и . Последовательно применяя этот результат к и её подгруппам, его можно обобщить в следующем виде[3][17]:
Вычисление порядка и перечисление элементовОписанное выше представление обладает такими свойствами:
Чтобы также иметь возможность проверять элементы на принадлежность порождённой подгруппе, нужно рассматривать ряды подгрупп особого вида, а именно — составленные из стабилизаторов[7]. Орбиты и стабилизаторыПусть действует на множестве . Выберем набор элементов и построим ряд подгрупп так, чтобы выполнялось , где — стабилизатор элемента . Другими словами, — это подгруппа элементов , которые переводят каждый из элементов в себя[7]. При таком подходе на каждом следующем шаге часть множества , на которую нетривиально действует очередная подгруппа , будет уменьшаться на один элемент, а порядок подгруппы, с которой ведётся работа, — хотя бы в два раза. Из этого следует, что понадобится итераций алгоритма, прежде чем будет найдено искомое разбиение[18]. Для построения смежных классов нужно воспользоваться тем, что существует взаимно-однозначное соответствие (биекция) между элементами орбиты и левыми смежными классами стабилизатора [19]. Доказательство По теореме об орбитах и стабилизаторах множество смежных классов и орбита равномощны. Сопоставим каждому элементу элемент орбиты . Пусть , тогда и множества и совпадают. Но из этого следует, что также совпадают и : Каждому смежному классу был поставлен в соответствие ровно один элемент орбиты. В силу того, что смежные классы покрывают всю группу , все сопоставленные элементы различны. Значит, это действительно биекция. ■ Из доказательства следует, что в качестве представителей смежных классов можно брать элементы, реализующие различные точки орбиты [19]. Проверка принадлежностиОбозначим через такой элемент , что . Разбиение в ряд стабилизаторов позволит проверять элемент на принадлежность группе[7]:
Эти свойства позволяют сделать переход от к , что в итоге приведёт к тому, что текущий элемент должен лежать в . Если это действительно так, то , откуда можно выразить [7]. Вычисление орбитыПусть у группы есть порождающее множество . Орбиту любого элемента под действием группы можно организовать в дерево следующего вида[17]:
Описанное дерево можно построить обходом в глубину, для этого нужно в каждой вершине перебирать элемент , пока не окажется, что для ещё не была выделена вершина[17]. Пример реализации на языке Python: # Строит дерево орбиты по заданному элементу w и порождающему множеству S
def build_schreier_tree(w, S, orbit):
for g in S:
if g[w] not in orbit:
orbit[g[w]] = apply(g, orbit[w])
build_schreier_tree(g[w], S, orbit)
Здесь функция возвращает результат применения групповой операции к элементам и в качестве первого и второго аргумента, а в хранится элемент . Лемма ШрайераИз леммы Шрайера следует, что стабилизатор порождается множеством генераторов Шрайера: . Этот результат позволяет по порождающему множеству для и орбите элемента построить порождающее множество для . Возможная реализация для функции, возвращающей новое порождающее множество[20]: # Принимает порождающее множество для G_{w-1} и орбиту элемента w
# Возвращает порождающее множество для G_w
def make_gen(S, orbit):
n = len(next(iter(S)))
newS = set()
for s in S:
for u in orbit:
newS.add(reduce(apply, [inverse(orbit[s[u]]), s, orbit[u]]))
return newS
Этим алгоритм не исчерпывается, так как хотя размер нового порождающего множества и зависит полиномиально от размера орбиты и старого порождающего множества для одного отдельного вызова, в совокупности по всем вызовам данной функции размер порождающего множества растёт экспоненциально[2]. Просеивание генераторовЧтобы избежать неконтролируемого роста порождающих множеств, необходимо применять процедуру просеивания. Для этого потребуется следующее утверждение[3][20]:
Доказательство Для начала докажем следующую лемму:
Доказательство Пусть после применения одной из этих операций мы получили множество . Очевидно, что . С другой стороны, эти преобразования могут быть обращены преобразованиями того же типа, поэтому . Значит, . ■ С помощью таких преобразований мы можем привести множество к такому виду, что для любой пары в наборе есть не более одного элемента такого, что: Этого можно добиться, добавляя элементы в новое множество по одному и действуя аналогично методу Гаусса:
Данный алгоритм использует только обозначенные выше элементарные операции, поэтому . Заметим, что если , то , поэтому переход к от в алгоритме является корректным и каждой паре действительно соответствует не больше одной перестановки. Учитывая, что всего таких пар не больше , получаем требуемое утверждение.■ Описанная в доказательстве процедура называется фильтром Симса и работает за [21]. Её реализация может выглядеть так: # Принимает порождающее множество S
# Возвращает прореженное порождающее множество S'
def normalize(S):
n = len(next(iter(S)))
newS = set()
base = [{} for i in range(n)]
for s in S:
for x in range(0, n):
if s[x] != x:
if s[x] in base[x]:
s = apply(inverse(s), base[x][s[x]])
else:
base[x][s[x]] = s
newS.add(s)
break
return newS
Помимо фильтра Симса для поиска небольшого набора может использоваться фильтр Джеррума[22]. В отличие от фильтра Симса, который находит набор из не более, чем элементов, фильтр Джеррума находит набор из не более чем элементов. В то же время фильтр Джеррума работает за , поэтому в случае алгоритма Шрайера — Симса предпочтительнее использовать именно фильтр Симса[21]. АлгоритмВсё вышенаписанное вместе даёт алгоритм, который может быть лаконично реализован следующим образом[20]: # Принимает порождающее множество S = s1, ..., sk
# Возвращает трансверсали смежных классов U1, ..., Uk
def schreier_sims(S):
n = len(next(iter(S)))
ans = []
w = 0
while S:
orbit = {}
orbit[w] = tuple(range(n))
build_schreier_tree(w, S, orbit)
ans += [[orbit[i] for i in orbit]]
S = normalize(make_gen(S, orbit))
w += 1
return ans
По шагам его действия имеют следующий смысл:
На выходе алгоритм вернёт список, элементами которого являются трансверсали смежных классов . Время работы алгоритмаВсего алгоритм требует не больше итераций. Каждая итерация состоит из:
Величина в случае, когда дан набор , на протяжении алгоритма не меняется и равна . Размер порождающего множество изначально равен , а на каждом последующем шаге не превышает . Таким образом, общее время работы алгоритма в приведённой реализации можно оценить как [8][12][13]. Вариации алгоритмаПсевдо-линейные версииРанее было показано, что алгоритм требует итераций. В общем случае размер группы может быть порядка , и в таком случае по формуле Стирлинга , что заведомо больше . Но в некоторых случаях порядок группы небольшой, в связи с чем выгоднее иметь алгоритм, который зависит от , а не — например, когда речь идёт о какой-то известной группе, которая задана как группа перестановок[12]. По теореме Кэли любая конечная группа изоморфна некоторой группе перестановок. Степень такой группы может быть большой, но для многих групп их порядок таков, что . Например, диэдральная группа изоморфна группе перестановок, порождённой циклическим сдвигом и отражением . То есть степень данной группы равна , а порядок — , и . Для таких групп можно рассматривать алгоритмы со временем работы , которые называются псевдо-линейными[12]. В попытке приблизить алгоритм к псевдо-линейному и снизить степень , входящую в его время работы, Шереш пришёл к версиям алгоритма, требующим[18]:
Вероятностная версияПервая рабочая вероятностная версия алгоритма была разработана Джефри Леоном в 1980 году[11]. Обычно именно её имеют в виду, когда говорят про вероятностный метод Шрайера — Симса. В нём при прореживании генераторов Шрайера данная процедура досрочно прекращалась, если 20 генераторов подряд оказывались разложенными на множители. Шереш показал, что в совокупности с некоторыми оптимизациями эта процедура даёт следующее утверждение[5]:
В современных системах компьютерной алгебры обычно используются модификации данной версии алгоритма с различными эвристиками для ускорения работы программы[5]. Примечания
Литература
|