1 общие сведения о gap - Dr. Alexander Konovalov

advertisement
СИСТЕМА КОМПЬЮТЕРНОЙ АЛГЕБРЫ
GAP
Александр Б. Коновалов (Alexander B. Konovalov). E-mail: konovalov@member.ams.org
Да нный до кумент я вля ется э лектр о нно й вер си ей следую щего и зда ни я: Ко но ва ло в А.Б.
Си стема ко мп ью тер но й а лгебр ы GAP. Мето ди чески е ука за ни я. - За п о р о жье: За п о р о жски й
го суда р ственный уни вер си тет, 1 9 9 9 . - 4 2 с.
С О Д Е Р Ж А Н И Е
1 ОБЩИЕ СВЕДЕНИЯ О GAP ..........................................................................................................................................2
1.1 КРАТКАЯ ХАРАКТЕРИСТИКА GAP ..................................................................................................................................2
1.2 ЗАПУСК GAP И ВЫХОД ИЗ СИСТЕМЫ .............................................................................................................................2
1.3 ПРИМЕРЫ ПРОСТЕЙШИХ ВЫЧИСЛЕНИЙ .........................................................................................................................2
2 ЯЗЫК ПРОГРАМИРОВАНИЯ GAP .............................................................................................................................3
2.1 СИМВОЛЫ И КАТЕГОРИИ СЛОВ В GAP ...........................................................................................................................3
2.2 КЛЮЧЕВЫЕ СЛОВА .........................................................................................................................................................3
2.3 ИДЕНТИФИКАТОРЫ ........................................................................................................................................................3
2.4 ВЫРАЖЕНИЯ ...................................................................................................................................................................3
2.5 ОБРАЩЕНИЯ К ФУНКЦИЯМ .............................................................................................................................................4
2.6 СРАВНЕНИЕ ВЫРАЖЕНИЙ ...............................................................................................................................................4
2.7 АРИФМЕТИЧЕСКИЕ ОПЕРАТОРЫ .....................................................................................................................................4
2.8 ПРИСВАИВАНИЯ .............................................................................................................................................................4
2.9 ВЫЗОВ ПРОЦЕДУРЫ ........................................................................................................................................................5
2.10 КОМАНДА IF .................................................................................................................................................................5
2.11 ЦИКЛ WHILE ...............................................................................................................................................................5
2.12 ЦИКЛ REPEAT .............................................................................................................................................................5
2.13 ЦИКЛ FOR ....................................................................................................................................................................6
2.14 ФУНКЦИИ .....................................................................................................................................................................6
2.15 КОМАНДА RETURN ....................................................................................................................................................7
3 СТРУКТУРЫ ДАННЫХ .................................................................................................................................................7
3.1 КОНСТАНТЫ И ОПЕРАТОРЫ ............................................................................................................................................7
3.2 ПЕРЕМЕННЫЕ И ПРИСВАИВАНИЯ ...................................................................................................................................8
3.3 ФУНКЦИИ .......................................................................................................................................................................8
3.4 СПИСКИ ..........................................................................................................................................................................8
3.5 ТОЖДЕСТВЕННОСТЬ И РАВЕНСТВО СПИСКОВ ..............................................................................................................10
3.6 МНОЖЕСТВА ................................................................................................................................................................10
3.7 ВЕКТОРЫ И МАТРИЦЫ ..................................................................................................................................................11
3.8 ЗАПИСИ.........................................................................................................................................................................12
3.9 АРИФМЕТИЧЕСКИЕ ПРОГРЕССИИ .................................................................................................................................13
3.10 ИСПОЛЬЗОВАНИЕ ЦИКЛОВ .........................................................................................................................................13
3.11 ДАЛЬНЕЙШИЕ ОПЕРАЦИИ СО СПИСКАМИ ..................................................................................................................14
3.12 ФУНКЦИИ ...................................................................................................................................................................14
4 ОПЕРАЦИИ НАД ГРУППАМИ И ИХ ЭЛЕМЕНТАМИ ........................................................................................16
4.1
4.2
4.3
4.4
4.5
4.6
5
ЗАДАНИЕ ГРУППЫ ПОДСТАНОВОК................................................................................................................................16
ЗАДАНИЕ ПОДГРУППЫ ГРУППЫ ПОДСТАНОВОК ...........................................................................................................16
ПРОСТЕЙШИЕ СВОЙСТВА ГРУППЫ. СИЛОВСКИЕ ПОДГРУППЫ. ...................................................................................16
ДРУГИЕ ВИДЫ ПОДГРУПП .............................................................................................................................................18
ФАКТОРГРУППЫ ...........................................................................................................................................................19
КЛАССЫ СОПРЯЖЕННЫХ ЭЛЕМЕНТОВ .........................................................................................................................20
СОЗДАНИЕ И ЗАПУСК ПРОГРАММ НА ЯЗЫКЕ GAP....................................................................................20
СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ .........................................................................................................22
ПРИЛОЖЕНИЕ ..................................................................................................................................................................23
1
1 ОБЩИЕ СВЕДЕНИЯ О GAP
1.1 КРАТКАЯ ХАРАКТЕРИСТИКА GAP
GAP (Groups, Algorithms and Programming) [1] является системой компьютерной алгебры, задуманной как
инструмент вычислительной теории групп, и впоследствии распространившейся на смежные разделы алгебры.
Первоначально GAP разрабатывался в г.Аахен, Германия (Lehrstuhl D für Mathematik, RWTH). В настоящее время
центр разработки GAP и технической поддержки его пользователей находится в Шотландии (School of
Mathematical and Computational Sciences, University of St.-Andrews).
Основные особенности GAP:
 язык программирования, внешне напоминающий Паскаль;
 стандартные типы основных алгебраических объектов: групп (подстановок, абстрактных, матричных),
колец, полей;
 удобные типы переменных, в т.ч. оперативно изменяемые списки и записи;
 более 4 тысяч библиотечных функций;
 обширная библиотека данных, включая практически все группы, порядок которых не превосходит 1000;
 прикладные программы, поставляемые вместе с GAP, охватывают такие разделы алгебры, как
комбинаторная теория групп, конечные простые группы, теория представлений групп, теория графов, в
т.ч. их группы автоморфизмов, теория кодирования, кристаллографические группы, группы Галуа и
многое другое;
 подробное и удобное описание (около 1600 стр.) в формате «гипертекст»;
 бесплатное получение по сети Internet вместе с исходными текстами, являющимися незаменимым
наглядным пособием для освоения GAP;
 работа в операционных системах DOS, Windows, Unix, Linux, MacOS;
 работа с процессором типа 386 и выше с ОЗУ от 8 Mb;
 занимаемое место на диске - от 10 до 100 Mb в зависимости от объема инсталляции;
 способность работать с ОЗУ до 128 Mb и файлом подкачки до 128 Mb;
Дальнейшая информация о GAP и условиях его распространения может быть получена по адресу:
The GAP Group, Mathematical Institute, St. Andrews, Scotland; tel. +44/1334/463251, fax 463278;
E-mail:gap@dcs.st-and.ac.uk; http://www-gap.dcs.st-and.ac.uk/~gap
1.2 ЗАПУСК GAP И ВЫХОД ИЗ СИСТЕМЫ
Запуск GAP в MS-DOS осуществляется с помощью командного файла gap.bat, который должен
находиться в каталоге, указанном в команде PATH в файле autoexec.bat. Если во время работы с GAP
необходимо чтение программ (файлов с расширением "g"), перед запуском GAP рекомендуется перейти в
содержащий эти программы каталог (здесь и далее предполагается, что читатель уже владеет необходимыми
навыками работы с ПЭВМ).
При успешном запуске GAP на экране появится эмблема GAP и приглашение системы, которое имеет
следующий вид:
gap>
Для выхода из системы применяется команда quit; (заметим, что любая команда завершается точкой с
запятой).
Примечание. Для дублирования введенных команд и выводимых на экран результатов в текстовом файле
используется команда LogTo("filename.log");. Ведение файла протокола может быть остановлено
командой LogTo(); (например, чтобы просмотреть его содержимое в другом окне Windows, не прерывая сеанса
работы с GAP).
1.3 ПРИМЕРЫ ПРОСТЕЙШИХ ВЫЧИСЛЕНИЙ
Вы можете использовать GAP в качестве обыкновенного калькулятора:
Пример 1:
gap> (9 - 7) * (5 + 6);
22
gap>
Пример 2:
gap> (9 - 7) * (5 + 6)
> ; # знак ">" - промежуточное приглашение GAP
22
gap>
2
2 ЯЗЫК ПРОГРАМИРОВАНИЯ GAP
2.1 СИМВОЛЫ И КАТЕГОРИИ СЛОВ В GAP
GAP воспринимает следующие символы: цифры, буквы (верхний и нижний регистры), пробел, символы
табуляции и новой строки, а также специальные символы:
"
'
(
)
*
+
,
_
.
/
:
;
<
=
>
~
[
\
]
^
_
{
}
#
Составленные из символов слова относятся к следующим категориям:
 ключевые слова (зарезервированные последовательности букв нижнего регистра)
 идентификаторы (последовательности цифр и букв, содержащая не менее одной буквы и не являющаяся
ключевым словом)
 строки (последовательности произвольных символов, заключенная в двойные кавычки)
 целые числа (последовательности цифр)
 операторы и ограничители в соответствии со следующим списком:
+
*
/
^
~
=
<>
<
<=
>
>=
:=
.
..
->
,
;
[
]
{
}
(
)
Следует заметить, что пробелы могут быть использованы для повышения удобочитаемости текста, так как
любая последовательность пробелов воспринимается GAP как один пробел. Таким образом, команда
if i<0 then a:=-i;else a:=i;fi;
может быть записана следующим образом:
if i < 0 then
# если i отрицательное
a := -i;
else
# иначе
a := i;
fi;
2.2 КЛЮЧЕВЫЕ СЛОВА
Ключевыми словами GAP являются следующие слова:
and
for
not
until
do
function
od
while
elif
if
or
quit
else
in
repeat
end
local
return
fi
mod
then
2.3 ИДЕНТИФИКАТОРЫ
Идентификаторы состоят из букв, цифр, символов «_», и должны содержать не менее одной буквы или
символа «_». При этом регистр является существенным. Примеры идентификаторов:
a
foo
LongIdentifier
hello
Hello
HELLO
x100
100x
_100
underscores_case
MixedCase
2.4 ВЫРАЖЕНИЯ
Примерами выражений являются: переменные, обращения к функциям, целые числа, перестановки, строки,
функции, списки, записи. С помощью операторов из них могут быть составлены более сложные выражения.
Операторы разбиты на три класса:
 операторы сравнения:
=
<>
<=
in
 арифметические операторы: +
*
/
mod
^
 логические операторы:
not
and
or
Пример 1:
gap>2*2;; #два знака ";" подавляют вывод на экран
gap>2*2+9=Fibonacci(7) and Fibonacci(13) in Prime;
true
Следует различать глобальные и локальные переменные, различия которых можно видеть из следующего
примера:
Пример 2:
3
g := 0;
# глобальная переменная g
x := function ( a, b, c )
local
y;
g := c;
# c - аргумент функции x
y := function ( y )
local d, e, f;
d := y; # y - аргумент функции y
e := b; # b - аргумент функции x
f := g; # g - глобальная переменная g
return d + e + f;
end;
return y(a); # y-локальная переменная функции x
end;
Формат:
2.5 ОБРАЩЕНИЯ К ФУНКЦИЯМ
function-var()
function-var( arg-expr {, arg-expr} )
Пример:
gap> Fibonacci( 11 );
# обращение к функции "Fibonacci" с аргументом 11
89
gap> G.operations.RightCosets(G,Intersection(U,V));;
#обращение к функции "G.operations.RightCosets",
#в котором второй аргумент определяется
#обращением к другой функции
2.6 СРАВНЕНИЕ ВЫРАЖЕНИЙ
Формат:
left-expr = right-expr
left-expr <> right-expr
Примечание: любые объекты сравнимы между собой. Объекты различных типов всегда различны, т.е. =
приведет к false, и <> — к true. Кроме того, для них определено отношение «меньше».
Операторы сравнения имеют больший приоритет по сравнению с логическими операторами, но меньший по
сравнению с арифметическими. Например, a*b = c and d интерпретируется как ((a*b)=c) and d). Еще
один пример (сравнение, левая часть которого является выражением ):
gap> 2 * 2 + 9 = Fibonacci(7);
true
2.7 АРИФМЕТИЧЕСКИЕ ОПЕРАТОРЫ
+ right-expr
- right-expr
left-expr + right-expr
left-expr - right-expr
left-expr * right-expr
left-expr / right-expr
left-expr mod right-expr
left-expr ^ right-expr
Значение, как правило, зависит от типа операндов. Mod определен только для целых и рациональных чисел.
Для элемента группы ^ означает возведение в степень, если правый операнд - целое число, а если он — также
элемент группы, то сопряжение с его помощью. Приоритет операторов (по убыванию):
1) ^
2) унарные + и 3) *, /, mod
4) + и Пример: -2 ^ -2 * 3 + 1 означает (-(2 ^ (-2)) * 3) + 1 .
Арифметические операторы имеют наивысший приоритет по сравнению с операторами сравнения и
логическими операторами.
Формат:
2.8 ПРИСВАИВАНИЯ
Командами в GAP называются: присваивания, вызовы процедур, структуры if, while, repeat, for, а
также команда return. Все команды заканчиваются знаком « ; ».
Присваивания имеют формат
var := expr;
Пример:
4
gap> S6 := rec( size := 720 );; S6;
rec(
size := 720 )
gap> S6.generators := [ (1,2), (1,2,3,4,5) ];; S6;
rec(
size := 720,
generators := [ (1,2), (1,2,3,4,5) ] )
gap> S6.generators[2] := (1,2,3,4,5,6);; S6;
rec(
size := 720,
generators := [ (1,2), (1,2,3,4,5,6) ] )
2.9 ВЫЗОВ ПРОЦЕДУРЫ
Формат: procedure-var();
procedure-var( arg-expr {, arg-expr} );
Различие между процедурами и функциями введено для удобства, GAP же их не различает. Функция
возвращает значение, но не производит побочных эффектов. Процедура не возвращает никакого значения, но
производит какое-либо действие (например, процедуры Print, Append, Sort).
2.10 КОМАНДА IF
Формат: if bool-expr1 then statements1
{ elif bool-expr2 then statements2 }
[ else statements3 ]
fi;
При этом частей elif может быть произвольное количество или ни одной. Часть else также может
отсутствовать.
Пример 1: в командах
if expr1 then
if expr2 then stats1
else stats2 fi;
fi;
else относится ко второму if, тогда как в командах
if expr1 then
if expr2 then stats1 fi;
else stats2
fi;
else относится к первому if.
Пример 2:
gap> i := 10;;
gap> if 0 < i then
>
s := 1;
>
elif i < 0 then
>
s := -1;
>
else
>
s := 0;
>
fi;
gap> s;
1
# знак i
2.11 ЦИКЛ WHILE
Формат: while bool-expr do statements od;
Последовательность команд statements выполняется, пока истинно условие bool-expr. При этом
сначала проверяется условие, а затем, если оно истинно, выполняются команды. Если уже при первом обращении
условие ложно, то последовательность команд statements не выполнится ни разу.
Пример:
gap> i := 0;; s := 0;;
gap> while s <= 200 do
>
i := i + 1; s := s + i^2;
>
od;
gap> s;
204
Формат:
2.12 ЦИКЛ REPEAT
repeat statements until bool-expr;
5
Последовательность команд statements выполняется, пока истинно условие bool-expr. При этом
сначала выполняются команды, а затем проверяется условие. Таким образом, при любом начальном значении
условия набор команд statements выполнится, по крайней мере, один раз.
Пример (вычисление наименьшей суммы квадратов первых n последовательных натуральных чисел,
превышающей 200):
gap> i := 0;; s := 0;;
gap> repeat
>
i := i + 1; s := s + i^2;
>
until s > 200;
gap> s;
204
2.13 ЦИКЛ FOR
Формат:
for simple-var in list-expr do statements od;
При этом последовательность команд statements выполняется для каждого элемента из списка listexpr. Цикл for эквивалентен циклу while:
loop-list := list;
loop-index:= 1;
while loop-index <= Length(loop-list) do
variable := loop-list[loop-index];
...
statements
...
loop-index := loop-index+1;
od;
Список list часто является последовательностью. Команда
for variable in [from..to] do statements od;
соответствует распространенной в других языках команде
for variable from from to to do statements od;
Пример:
gap> s := 0;;
gap> for i in [1..100] do
>
s := s + i;
> od;
gap> s;
5050
В следующем примере изменение списка приводит к выполнению команд для новых его элементов:
gap> l := [ 1, 2, 3, 4, 5, 6 ];;
gap> for i in l do
>
Print( i, " " );
>
if i mod 2 = 0 then Add( l, 3*i/2 ); fi;
> od; Print( "\n" );
1 2 3 4 5 6 3 6 9 9
gap> l;
[ 1, 2, 3, 4, 5, 6, 3, 6, 9, 9 ]
А в следующем — не приводит:
gap> l := [ 1, 2, 3, 4, 5, 6 ];;
gap> for i in l do
>
Print( i, " " );
>
l := [];
> od; Print( "\n" );
1 2 3 4 5 6
gap> l;
[ ]
2.14 ФУНКЦИИ
Формат: function ( [ arg-ident {, arg-ident} ] )
[ local loc-ident {, loc-ident} ; ]
statements
end
Пример функции, которая определяет n-е число Фибоначчи:
gap> fib := function ( n )
>
local f1, f2, f3, i;
>
f1 := 1; f2 := 1;
6
>
for i in [3..n] do
>
f3 := f1 + f2; f1 := f2; f2 := f3;
>
od;
>
return f2;
>
end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
Ту же функцию можно определить рекурсивно:
gap> fib := function ( n )
>
if n < 3 then
>
return 1;
>
else
>
return fib(n-1) + fib(n-2);
>
fi;
>
end;;
gap> List( [1..10], fib );
[ 1, 1, 2, 3, 5, 8, 13, 21, 34, 55 ]
Заметим, что рекурсивная версия требует 2 * fib(n)-1 шагов для вычисления fib(n), тогда как итеративная
требует только n-2 шага. Обе, однако, не являются оптимальными, так как библиотечная функция Fibonacci
требует порядка Log(n) шагов.
Запись arg-ident -> expr является краткой записью для функции
function ( arg-ident ) return expr; end.
Здесь arg-ident - один идентификатор, т.е. таким образом нельзя задать функцию от нескольких
переменных.
Пример типичного использования такой записи:
gap> Sum( List( [1..100], x -> x^2 ) );
338350
2.15 КОМАНДА RETURN
Формат:
return;
return expr;
Первая форма прерывает выполнение внутренней (при вызове одной функции из другой) функции и
передает управление вызывающей функции, не возвращая при этом никакого значения. Вторая, кроме того,
возвращает значение выражения expr.
3 СТРУКТУРЫ ДАННЫХ
3.1 КОНСТАНТЫ И ОПЕРАТОРЫ
Основные принципы задания констант и действий над ними видны из следующих примеров:
Пример 1:
gap> 12345/25;
2469/5
gap> -3; 17 - 23;
-3
-6
gap> 3^132;
9550049507968252368931907017744140119199351389743
43129836853841
Пример 2 (операции с подстановками):
gap> (1,2,3);
(1,2,3)
gap> (1,2,3) * (1,2);
(2,3)
gap> (1,2,3)^-1;
(1,3,2)
gap> 2^(1,2,3);
3
gap> (1,2,3)^(1,2);
(1,3,2)
7
Пример 3 (задание строки):
gap> 'a';
'a'
3.2 ПЕРЕМЕННЫЕ И ПРИСВАИВАНИЯ
Порядок присваивания демонстрируется следующим примером:
Пример 1:
gap> a:= (9 - 7) * (5 + 6);
22
gap> a;
22
gap> a:= 10;
10
gap> a * (a + 1);
110
Примечание 1. После присваивания присвоенное значение отображается в следующей строке вывода. Это
можно подавить, если завершить команду двумя знаками «;» вместо одного:
gap> w:= 2;;
Примечание 2. Всякий раз, когда GAP возвращает значение, печатая его в следующей после команды
строке, это значение присваивается переменной с именем last :
gap> (9 - 7) * (5 + 6);
22
gap> a:= last;
22
Аналогичным образом определяются переменные last2 и last3.
3.3 ФУНКЦИИ
GAP содержит более 4000 стандартных функций. Пример обращения к нескольким из них приведен ниже:
Пример 1:
gap> Factorial(17);
355687428096000
gap> Gcd(1234, 5678);
2
gap> Print(1234, "\n");
1234
Кроме того, пользователь может вводить собственные функции. Наиболее просто это делается так:
Пример 2:
gap> cubed:= x -> x^3;
function ( x ) ... end
gap> cubed(5);
125
Другой способ определения функций и процедур изложен в пп. 2.14 и 3.12.
Порядок разработки программ на языке GAP описан в разделе 5.
3.4 СПИСКИ
Список является заключенным в квадратные скобки набором объектов, разделенных запятыми. Например,
список из первых десяти простых чисел можно задать следующим образом:
gap> primes:=[2, 3, 5, 7, 11, 13, 17, 19, 23, 29];
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
Затем к нему можно добавить следующие два простых числа:
gap> Append(primes, [31, 37]);
gap> primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37 ]
Если добавляется только один элемент, это можно сделать и по-другому:
gap> Add(primes, 41);
gap> primes;
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41 ]
Указать отдельный элемент списка можно по его номеру в списке:
gap> primes[7];
17
Этот же механизм позволяет присвоить значение существующему или новому элементу списка (функция
Length определяет длину списка):
8
gap> Length(primes);
13
gap> primes[14]:= 43;
43
gap> primes;
[ 2, 3, 5, 7,11,13,17,19,23,29,31,37,41,43 ]
При этом значение не обязательно должно присваиваться следующему элементу списка. Например, если
двадцатым простым числом является 71, мы можем сразу присвоить значение 71 двадцатому элементу списка
primes, пропуская недостающие элементы. Полученный список будет иметь длину 20:
gap> primes[20]:= 71;
71
gap> primes;
[ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,,,,,, 71 ]
gap> Length(primes);
20
Список должен быть создан перед заданием его элемента (например, быть пустым списком [ ]):
gap> lll[1]:= 2;
Error, Variable: 'lll' must have a value
gap> lll:= [];;
gap> lll[1]:= 2;
2
Функция Position возвращает номер первого элемента списка, имеющего заданное значение. Если в
списке нет элемента с заданным значением, функция возвращает false:
gap> Position(primes, 17);
7
gap> Position(primes, 20);
false
Заметим, что при всех приведенных выше изменениях списка primes длина списка изменялась
автоматически.
Функция IsBound для списков показывает, содержит ли список элемент с заданным номером (для
записей— содержит ли запись указанное поле):
gap> k:= [ , 2, 3, , 5, , 7, , , , 11 ];;
gap> IsBound(k[7]); IsBound(k[4]); IsBound(k[20]);
true
false
false
Список может состоять из объектов различных типов, например:
gap> lll:= [true, "This is a String",,, 3];
[ true, "This is a String",,, 3 ]
Далее, список может являться частью другого списка или самого себя:
gap> lll[3]:= [4,5,6];; lll;
[ true, "This is a String", [ 4, 5, 6 ],, 3 ]
gap> lll[4]:= lll;
[ true, "This is a String", [ 4, 5, 6 ], ~, 3 ]
Здесь знак « ~ » в четвертой позиции обозначает объект, вывод которого на экран (печать) производится в
данный момент.
Строки являются частным случаем списков, и печатаются без разделителей. Примеры задания строк и
операций над ними:
gap>s1:=['H','a','l','l','o','','w','o','r','l','d','.'];
"Hallo world."
gap> s2 := "Hallo world.";
"Hallo world."
gap> s1 = s2;
true
gap> s2[7];
'w'
Извлечение и изменение подмножеств списка производит оператор { }:
gap> sl := lll{ [ 1, 2, 3 ] };
[ true, "This is a String", [ 4, 5, 6 ] ]
gap> sl{ [ 2, 3 ] } := [ "New String", false ];
[ "New String", false ]
gap> sl;
[ true, "New String", false ]
9
3.5 ТОЖДЕСТВЕННОСТЬ И РАВЕНСТВО СПИСКОВ
Для изучения способов управления сложными структурами данных в GAP важно понимать различия между
тождественными и равными объектами. В данном разделе это различие демонстрируется на примере списков.
Аналогичные примеры могут быть подобраны и для записей.
Два списка равны (т.е. оператор сравнения = возвращает true) тогда и только тогда, когда они имеют
одинаковую длину и их соответствующие элементы равны.
Пример:
gap> numbers:= primes;
[ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,,,,,,71 ]
gap> numbers = primes;
true
Теперь изменим список numbers и снова сравним его с primes.
gap> primes[3]:= 4;
4
gap> numbers = primes;
true
Оказывается, что списки numbers и primes снова равны, а распечатав список primes, мы увидим, что
primes[3]:=4. Это объясняется тем, что списки primes и numbers не только равны, но и идентичны.
Идентификаторы primes и numbers указывают на один и тот же список, и изменения в нем происходят при
указании любого из его имен. Присваивание numbers:= primes создает не новый список, а только товое имя
для уже существующего списка.
Если необходимо изменить список, совпадающий по содержанию с primes, таким образом, чтобы сам
список primes при этом не изменился, необходимо создать копию списка primes с помощью функции Copy (в
следующем примере предварительно восстановим старое значения primes.)
gap> primes[3]:= 5;
5
gap> primes;
[ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,,,,,,71 ]
gap> numbers:= Copy(primes);
[ 2,3,5,7,11,13,17,19,23,29,31,37,41,43,,,,,,71 ]
gap> numbers = primes;
true
gap> numbers[3]:= 4;
4
gap> numbers = primes;
false
Примечание. Единственными объектами, которые могут быть изменены таким способом, являются списки и
записи, т.к. только эти объекты в GAP могут состоять из других объектов. Например, после выполнения
следующих команд значения i и j будут соответственно равны 2 и 1:
gap> i:= 1;; j:= i;; i:= i+1;;
Упражнение. Объяснить, что происходит в результате выполнения команд:
gap> l:= [];
[ ]
gap> l:= [l];
[ [ ] ]
gap> l[1]:= l;
[ ~ ]
3.6 МНОЖЕСТВА
Множествами в GAP называются списки специального вида. Элементы множества расположены
последовательно (т.е. не содржат пробелов, как, например, список [2,3,5,,,,,,,,31,37,41]), упорядочены
(порядок сортировки GAP определяет самостоятельно) и встречаются в списке только один раз. Множества, как и
списки, могут содержать объекты различных типов. Проверить, является ли объект множеством, можно с помощью
функции IsSet. Для каждого списка существует соответствующее ему множество, получаемое с помощью
функции Set.
Пример:
gap> fruits:=["apple", "strawberry", "cherry",
>
"plum", "apple"];;
gap> IsSet(fruits);
false
gap> fruits:= Set(fruits);
[ "apple", "cherry", "plum", "strawberry" ]
Заметим, что при этом исходный список fruits был изменен.
10
Для проверки принадлежности объекта множеству используется оператор in. Его также можно
использовать для проверки принадлежности к списку, однако в первом случае проверка выполняется быстрее, т.к.
сортировка позволяет использовать двоичный поиск вместо последовательного перебора.
gap> "apple" in fruits;
true
gap> "banana" in fruits;
false
Добавить к множеству новый элемент можно с помощью функции AddSet (обратите внимание на порядок
следования элементов):
gap> AddSet(fruits, "banana");
gap> fruits;
["apple", "banana", "cherry", "plum", "strawberry"]
gap> AddSet(fruits, "apple");
gap> fruits;
# 'fruits' не изменилось
["apple", "banana", "cherry", "plum", "strawberry"]
Пересечение, объединение и разность множеств определяются с помощью функций Intersection, Union
и Difference. При этом аргументы могут быть обычными списками, тогда как результат всегда будет являться
множеством.
Пример:
gap> breakfast:= ["tea", "apple", "egg"];
[ "tea", "apple", "egg" ]
gap> Intersection(breakfast, fruits);
[ "apple" ]
gap> Difference(breakfast,fruits);
[ "egg", "tea" ]
Те же операции над множествами производят функции IntersectSet, UniteSet и RemoveSet, но они
не возвращают результат, а заменяют им первый аргумент.
3.7 ВЕКТОРЫ И МАТРИЦЫ
Вектор является списком элементов, принадлежащих общему полю, не содержащим пробелов.
gap> v:= [3, 6, 2, 5/2];
[ 3, 6, 2, 5/2 ]
gap> IsVector(v);
true
Векторы умножаются на скаляры из любого поля, содержащего данное. Умножение двух векторов равной
длины дает их скалярное произведение.
gap> 2 * v;
[ 6, 12, 4, 5 ]
gap> v * 1/3; # это эквивалентно команде v/3;
[ 1, 2, 2/3, 5/6 ]
gap> v * v;
221/4 # скалярное произведение v на себя
Матрица —список векторов одинаковой длины, не содержащий пробелов:
gap> m:= [[1, -1, 1],
>
[2, 0, -1],
>
[1, 1, 1]];
[ [ 1, -1, 1 ], [ 2, 0, -1 ], [ 1, 1, 1 ] ]
gap> m[2][1];
2
Матрицы можно умножать на скаляры, векторы и другие матрицы (при соответствии размеров):
gap> m:= [[1, 2, 3, 4],
>
[5, 6, 7, 8],
>
[9,10,11,12]];
[ [1,2,3,4 ], [5,6,7,8], [9,10,11,12] ]
gap> PrintArray(m);
[ [
1,
2,
3,
4 ],
[
5,
6,
7,
8 ],
[
9, 10, 11, 12 ] ]
gap> [1, 0, 0, 0] * m;
Error, Vector *: vectors must have the same length
gap> [1, 0, 0] * m;
[ 1, 2, 3, 4 ]
gap> m * [1, 0, 0];
Error, Vector *: vectors must have the same length
gap> m * [1, 0, 0, 0];
[ 1, 5, 9 ]
11
gap> m * [0, 1, 0, 0];
[ 2, 6, 10 ]
Заметим, что умножение вектора на матрицу приводит к линейной комбинации строк матрицы, тогда как
умножение матрицы на вектор приводит к линейной комбинации ее столбцов. В последнем случае вектор
рассматривается как вектор-столбец. Подматрицы извлекаются или изменяются с помощью фигурных скобок:
gap> sm := m{ [ 1, 2 ] }{ [ 3, 4 ] };
[ [ 3, 4 ], [ 7, 8 ] ]
gap> sm{ [ 1, 2 ] }{ [2] } := [[1],[-1]];
[ [ 1 ], [ -1 ] ]
gap> sm;
[ [ 3, 1 ], [ 7, -1 ] ]
Первая пара скобок указывает выбранные строки, вторая - столбцы.
3.8 ЗАПИСИ
Другой способ создания новых структур данных — записи. Как и списки, записи —наборы других объектов
(которые называются компонентами, или полями), обращение к которым происходит не по номеру, а по имени.
Пример:
gap> date:= rec(year:=1992, month:="Jan", day:=13);
rec(
year := 1992,
month := "Jan",
day := 13 )
Изначально запись определяется как разделенный запятыми список присваиваний значений ее полям. Для
обращения к значению соответствующего поля записи необходимо указать имя записи и имя поля, разделив их
точкой. Определив запись, в дальнейшем можно добавлять к ней новые поля.
Пример:
gap> date.year;
1992
gap>date.time:=rec(hour:=19,minute:=23,second:=12);
rec(
hour := 19,
minute := 23,
second := 12 )
gap> date;
rec(
year := 1992,
month := "Jan",
day := 13,
time := rec(
hour := 19,
minute := 23,
second := 12 ) )
Большинство сложных структур, с которыми работает GAP, являются именно записями (например, группы,
групповые кольца, таблицы характеров).
GAP имеет множество стандартных функций (аргументы которых являются записями), которые изменяют
значения существующих полей или добавляют новые поля к своим аргументам. Так, функция Size вычисляет
размер(порядок) своего аргумента (например, группы) и сохраняет найденное значение в поле size. При
последующем обращении к этой функции вместо ее вычисления будет использовано сохраненное ее значение.
Для определения, является ли объект записью, применяется функция IsRecord. Стуктуру записи можно
получить с помощью функции RecFields:
gap> RecFields(date);
[ "year", "month", "day", "time" ]
Упражнение. Что происходит в результате выполнения команд:
gap> r:= rec();
rec(
)
gap> r:= rec(r:= r);
rec(
r := rec(
) )
gap> r.r:= r;
rec(
r := ~ )
12
3.9 АРИФМЕТИЧЕСКИЕ ПРОГРЕССИИ
Другим специальным видом списков являются целочисленные конечные арифметические прогрессии. Они
описываются первым, вторым и последним элементами, разделенными соответственно запятой или двумя точками,
и заключенными в квадратные скобки. Если прогрессия состоит из последовательных чисел, второй элемент может
быть опущен.
Пример:
gap>[1..999999]; #натуральные числа от 1 до 999999
[ 1 .. 999999 ]
gap>[1,2..999999];#эквивалентно предыдущей команде
[ 1 .. 999999 ]
gap>[1,3..999999]; # здесь шаг равен 2
[ 1, 3 .. 999999 ]
gap> Length( last );
500000
gap> [ 999999, 999997 .. 1 ];
[ 999999, 999997 .. 1 ]
3.10 ИСПОЛЬЗОВАНИЕ ЦИКЛОВ
Пример 1:
Вычислить произведение подстановок, являющихся элементами списка.
gap> pp:=[(1,3,2,6,8)(4,5,9), (1,6)(2,7,8)(4,9),
> (1,5,7)(2,3,8,6), (1,8,9)(2,3,5,6,4),
> (1,9,8,6,3,4,7,2) ];;
gap> prod:= ();
()
gap> for p in pp do
>
prod:= prod * p;
>
od;
gap> prod;
(1,8,4,2,3,6,5)
Пример 2:
Вычисление n! для n = 15.
gap> ff:= 1;
1
gap> for i in [1..15] do
>
ff:= ff * i;
>
od;
gap> ff;
1307674368000
Пример 3:
Разложить на простые множители число 1333, используя список простых чисел primes.
gap> n:= 1333;
1333
gap> factors:= [];
[ ]
gap> for p in primes do
>
while n mod p = 0 do
>
n:= n/p;
>
Add(factors, p);
>
od;
>
od;
gap> factors;
[ 31, 43 ]
gap> n;
1
Так как n=1, то процесс завершен (легко проверить, умножив 31 на 43).
Пример 4:
Составить список простых чисел, не превышающих 1000 (функция Unbind исключает элемент из списка).
gap> primes:= [];
[ ]
gap> numbers:= [2..1000];
[ 2 .. 1000 ]
gap> for p in numbers do
>
Add(primes, p);
>
for n in numbers do
>
if n mod p = 0 then
13
>
>
>
>
Unbind(numbers[n-1]);
fi;
od;
od;
3.11 ДАЛЬНЕЙШИЕ ОПЕРАЦИИ СО СПИСКАМИ
Существует более удобный способ умножения элементов списка из чисел или подстановок.
gap> Product([1..15]);
1307674368000
gap> Product(pp);
(1,8,4,2,3,6,5)
Аналогичным образом работает функция Sum.
Пример 1:
Аргументами функции List является список и имя функции. В результате будут создан список значений
заданной функции на элементах заданного списка. Например, для нахождения куба числа ранее была определена
функция cubed. Составим с ее помощью список кубов чисел от 2 до 10.
gap> List([2..10], cubed);
[ 8, 27, 64, 125, 216, 343, 512, 729, 1000 ]
Чтобы сложить все эти величины, мы можем применить функцию Sum к последнему списку. Это же можно
сделать, используя функцию cubed в качестве дополнительного аргумента функции Sum:
gap> Sum(last) = Sum([2..10], cubed);
true
Пример 2:
Получение списка простых чисел, меньших 30, из списка primes с помощью функции Filtered:
gap> Filtered(primes, x-> x < 30);
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
Пример 3:
Оператор { } извлекает часть списка, определяемую номерами начального и конечного элементов списка:
gap> primes{ [1 .. 10] };
[ 2, 3, 5, 7, 11, 13, 17, 19, 23, 29 ]
3.12 ФУНКЦИИ
Ранее было показано, как обратиться к библиотечным, т.е. стандартным функциям GAP. Данный раздел
посвящен разработке новых функций.
Пример 1:
Пусть, например, требуется задать простейшую функцию, которая печатает на экране текст «hello, world.».
gap> sayhello:= function()
> Print("hello, world.\n");
> end;
function ( ) ... end
При этом добавление к строке вывода символов «\n» приведет к тому, что следующее приглашение GAP
появится на новой строке, а не непосредственно после напечатанного текста.
Определение функции начинается с ключевого слова function, после которого в скобках указываются
формальные параметры. Скобки необходимы и в том случае, если параметры отсутствуют. Следует обратить
внимание на отсутствие точки с запятой после первой команды. Определение функции завершается ключевым
словом end.
Функция после ее определения является такой же переменной, как и целые числа, суммы и списки, и может
быть присвоена другой переменной. Завершающий знак «;» в приведенном примере не принадлежит к определению
функции, а завершает ее присвоение имени sayhello. После этого, в отличие от других присваиваний, значение
функции sayhello отображается в сокращенной форме function ( ) ... end, отображающей только ее
формальные параметры, как наиболее интересную часть. Полное значение sayhello может быть получено с
помощью функции Print:
gap> Print(sayhello, "\n");
function ( )
Print( "hello, world.\n" );
end
Обращение к данной функции произойдет по команде sayhello():
gap> sayhello();
hello, world.
Однако данный пример не является типичным, так как введенная нами функция не возвращает ни одно
значение, а только печатает текст.
Пример 2:
Задание функции, определяющей знак числа.
14
gap> sign:= function(n)
>
if n < 0 then
>
return -1;
>
elif n = 0 then
>
return 0;
>
else
>
return 1;
>
fi;
>
end;
function ( n ) ... end
gap> sign(0); sign(-99); sign(11);
0
-1
1
gap> sign("abc");
1
#strings are defined to be greater than 0
Пример 3:
Числа Фибоначчи определяются рекурсивно: f (1) = f (2) = 1,
f (n) = f (n-1) + f (n-2).
Так как функция в GAP может обращаться сама к себе, то функция для вычисления n-го числа Фибоначчи
может быть задана следующим образом:
gap> fib:= function(n)
>
if n in [1, 2] then
>
return 1;
>
else
>
return fib(n-1) + fib(n-2);
>
fi;
>
end;
function ( n ) ... end
gap> fib(15);
610
Упражнение: Добавить к данной функции проверку того, что n является натуральным числом.
Пример 4:
Функция gcd, вычисляющая наибольший общий делитель двух целых чисел по алгоритму Евклида, требует
создания локальных переменных в дополнение к формальным параметрам. Описание локальных переменных, если
они есть, должно предшествовать всем операторам, входящим в определение функции.
gap> gcd:= function(a, b)
>
local c;
>
while b <> 0 do
>
c:= b;
>
b:= a mod b;
>
a:= c;
>
od;
>
return c;
>
end;
function ( a, b ) ... end
gap> gcd(30, 63);
3
Пример 5:
Составим функцию, которая определяет количество разложений натурального числа (разложением данного
числа называется невозрастающая последовательность натуральных чисел, сумма которых равна данному числу).
Все множество разложений для данного числа n может быть разделено на подмножества в зависимости от
максимального элемента разложения. Тогда количество разложений для n равняется сумме по всем возможным i
количеств разложений для n-i, элементы которых меньше, чем i. Обобщая это, получаем, что количество
разложений числа n, элементы которых меньше, чем m, является суммой (по i < m,n) количества разложений для n-i
с элементами, меньшими, чем i. Отсюда получаем следующую функцию:
gap> nrparts:= function(n)
>
local np;
>
np:= function(n, m)
>
local i, res;
>
if n = 0 then
>
return 1;
>
fi;
>
res:= 0;
>
for i in [1..Minimum(n,m)] do
>
res:= res + np(n-i, i);
>
od;
>
return res;
15
>
end;
>
return np(n,n);
> end;
function ( n ) ... end
Желая составить функцию, которая имеет один аргумент, мы решили поставленную задачу с помощью
рекурсивной процедуры с двумя аргументами. Поэтому понадобилось фактически ввести две функции.
Единственной задачей одной из них является вызов другой с двумя равными аргументами.
При этом функция np является локальной по отношению к nrparts. Она могла бы быть определена и
независимо, но тогда идентификатор np уже не мог бы быть использован для других целей, а если бы это все-таки
произошло, функция nrparts не могла бы обратиться к функции np.
Теперь рассмотрим функцию np, имеющую две локальные переменные res и i. Переменная res используется
для суммирования, i - параметр цикла. Внутри цикла опять происходит обращение к функции np, но уже с другими
аргументами. Однако для быстродействия программы предпочтительнее избегать рекурсивных процедур, если
только можно без них обойтись.
Упражнение: Предложить решение последней задачи, не используя рекурсивные процедуры.
4 ОПЕРАЦИИ НАД ГРУППАМИ И ИХ ЭЛЕМЕНТАМИ
4.1 ЗАДАНИЕ ГРУППЫ ПОДСТАНОВОК
Данный раздел посвящен операциям над группами и их элементами. Определения и необходимые
теоретические сведения могут быть найдены в [2]-[6]. Приведенные ниже примеры используют группы
подстановок, но большинство используемых в них функций (в т.ч. Group, Size, SylowSubgroup) применяется и
к другим используемым в GAP видам групп, для каждого из которых вычисления производятся по специальному
алгоритму.
Зададим группу подстановок, которая порождается (записанными в виде произведения независимых циклов)
подстановками (1,2) и (1,2,3,4,5,6,7,8). Эта группа есть не что иное, как симметрическая группа S 8:
gap> s8:= Group( (1,2), (1,2,3,4,5,6,7,8) );
Group( (1,2), (1,2,3,4,5,6,7,8) )
4.2 ЗАДАНИЕ ПОДГРУППЫ ГРУППЫ ПОДСТАНОВОК
Группа S8 содержит знакопеременную группу A8, которая может быть задана как подгруппа, состоящая из
четных подстановок, или как ее коммутант:
gap> a8:= CommutatorSubgroup( s8, s8 );
Subgroup( Group( (1,2), (1,2,3,4,5,6,7,8) ),
[(1,3,2),(2,4,3),(2,3)(4,5),(2,4,6,5,3),
(2,5,3)(4,7,6),(2,3)(5,6,8,7) ] )
Таким образом, A8 описывается как подгруппа группы s8, которая порождается указанными шестью
подстановками. Это представление намного короче, чем внутренняя структура a8, (которую можно посмотреть с
помощью функций RecFields и PrintRec), но для понимания его вполне достаточно.
Если обращение к объекту происходит часть, удобно присвоить ему имя:
gap> s8.name:= "s8";
"s8"
gap> a8;
Subgroup( s8 ,[ (1,3,2), (2,4,3), (2,3)(4,5),
(2,4,6,5,3), (2,5,3)(4,7,6), (2,3)(5,6,8,7)] )
gap> a8.name:= "a8";
"a8"
gap> a8;
a8
Как только группа будет содержать поле name, вместо самого описания группы будет выводиться ее имя:
gap> copya8:= Copy( a8 );
a8
Несмотря на отсутствие связи между именем и идентификатором, их желательно выбирать согласованно.
4.3 ПРОСТЕЙШИЕ СВОЙСТВА ГРУППЫ. СИЛОВСКИЕ ПОДГРУППЫ.
Изучим группу a8. Она является записью, список полей которой возвращает функция RecFields:
gap> RecFields( a8 );
[ "isDomain", "isGroup", "parent", "identity",
"generators", "operations", "isPermGroup",
"1", "2", "3", "4", "5", "6", "stabChainOptions",
"stabChain", "orbit", "transversal",
"stabilizer", "name" ]
16
Многие функции сохраняют информацию о группе, добавляя новое поле в эту запись, что позволяет
избежать повторных вычислений. Но сейчас нас интересуют свойства самой группы, а не организация данных.
Сначала получим ее порядок и проверим, является ли она абелевой.
gap> Size( a8 ); IsAbelian( a8 ); IsPerfect( a8 );
20160
false
true
Теперь получим список простых делителей порядка группы:
gap> Set( Factors( Size( a8 ) ) );
[ 2, 3, 5, 7 ]
Для каждого из простых делителей p вычислим силовскую p-подгруппу, которую функция SylowSubgroup
сохрани в поле a8.sylowSubgroups:
gap> Set( Factors( Size( a8 ) ) );
[ 2, 3, 5, 7 ]
gap> for p in last do
>
SylowSubgroup( a8, p );
>
od;
gap> a8.sylowSubgroups;
[ , Subgroup(s8,[(1,5)(7,8), (1,5)(2,6),
(3,4)(7,8), (2,3)(4,6),(1,7)(2,3)(4,6)(5,8),
(1,2)(3,7)(4,8)(5,6)]),
Subgroup( s8, [ (3,8,7), (2,6,4)(3,7,8) ] ),,
Subgroup( s8, [ (3,7,8,6,4) ] ),,
Subgroup( s8, [ (2,8,4,5,7,3,6) ] ) ]
Поле sylowSubgroups является списком, p-м элементом которого является силовская p-подгруппа, если
такая существует (поэтому 1-й, 4-й и 6-й элементы списка не определены).
Исследуем силовскую 2-подгруппу. Сначала для удобства обозначим ее syl2, а затем определим ее размер:
gap> syl2:= last[2];;
gap> Size( syl2 );
64
Теперь вычислим ее нормализатор в a8:
gap> Normalizer( a8, syl2 );
Subgroup( s8, [ (3,4)(7,8), (2,3)(4,6),
(1,2)(3,7)(4,8)(5,6) ] )
Проверим, совпадает ли он с syl2:
gap> last = syl2;
true
Вычислим центр подгруппы syl2:
gap> Centre( syl2 );
Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8) ] )
Найдем централизатор cent последней подгруппы в a8, т.е. подгруппу элементов а8, перестановочных с
каждым элементом центра группы syl2:
gap> cent:= Centralizer( a8, last );
Subgroup( s8, [ ( 1, 5)( 2, 6)( 3, 4)( 7, 8),
(3,4)(7,8), (3,7)(4,8), (2,3)(4,6), (1,2)(5,6) ])
Найдем ее порядок:
gap> Size( cent );
192
Вычислим ряд коммутантов cent:
gap> DerivedSeries( cent );
[ Subgroup( s8, [ (1,5)(2,6)(3,4)(7,8), (3,4)(7,8),
(3,7)(4,8), (2,3)(4,6), (1,2)(5,6) ] ),
Subgroup( s8, [ (1,6,3)(2,4,5), (1,8,3)(4,5,7),
(1,7)(2,3)(4,6)(5,8), (1,5)(2,6) ] ),
Subgroup( s8, [ (1,3)(2,7)(4,5)(6,8),
(1,6)(2,5)(3,8)(4,7), (1,5)(3,4),
(1,5)(7,8) ] ),
Subgroup( s8, [ (1,5)(2,6)(3,4)(7,8) ] ),
Subgroup( s8, [ ] ) ]
Последний элемент полученного списка — тривиальная подгруппа, поэтому cent - разрешимая группа.
Порядки подгрупп, входящих в ряд коммутантов (производный ряд) удобно получить следующим образом:
gap> List( last, Size );
[ 192, 96, 32, 2, 1 ]
Вычислим теперь нижний центральный ряд группы cent:
gap> low:= LowerCentralSeries( cent );
[ Subgroup( s8, [ (1,5)(2,6)(3,4)(7,8), (3,4)(7,8),
17
(3,7)(4,8), (2,3)(4,6), (1,2)(5,6) ] ),
Subgroup( s8, [ (1,6,3)(2,4,5), (1,8,3)(4,5,7),
(1,7)(2,3)(4,6)(5,8), (1,5)(2,6) ] ) ]
4.4 ДРУГИЕ ВИДЫ ПОДГРУПП
Теперь покажем, как найти стабилизатор некоторого элемента множества, на котором действует группа
подстановок. Как видно из следующего примера, стабилизатором единицы является подгруппа порядка 2520 и
индекса 8, порожденная пятью подстановками:
gap> stab:= Stabilizer( a8, 1 );
Subgroup( s8, [ (2,5,6), (2,5)(3,6), (2,5,6,4,3),
(2,5,3)(4,6,8), (2,5)(3,4,7,8) ] )
gap> Size( stab );
2520
gap> Index( a8, stab );
8
С помощью функции Random получим случайный элемент из a8:
gap> Random( a8 );
(1,6,3,2,7)(4,5,8)
Новые подгруппы могут быть теперь получены путем поиска его централизатора, а затем комбинаций
сопряжения и пересечения уже известных подгрупп. Заметим, что, хотя мы формируем подгруппы, не выходя за
пределы а8, при выводе они описываются как подгруппы s8:
gap> Random( a8 );
(1,3,2,4,7,5,6)
gap> cent:= Centralizer( a8,(1,2)(3,4)(5,8)(6,7) );
Subgroup( s8, [ (1,2)(3,4)(5,8)(6,7), (5,6)(7,8),
(5,7)(6,8), (3,4)(6,7), (3,5)(4,8),
(1,3)(2,4) ] )
gap> Size( cent );
192
gap> conj:= ConjugateSubgroup( cent, (2,3,4) );
Subgroup( s8, [ (1,3)(2,4)(5,8)(6,7), (5,6)(7,8),
(5,7)(6,8), (2,4)(6,7), (2,8)(4,5),
(1,4)(2,3)] )
gap> inter:= Intersection( cent, conj );
Subgroup( s8, [ (5,6)(7,8), (5,7)(6,8), (1,2)(3,4),
(1,3)(2,4) ] )
gap> Size( inter ); IsElementaryAbelian( inter );
16
true
gap> norm:= Normalizer( a8, inter );
Subgroup( s8, [ (6,7,8), (5,6,8), (3,4)(6,8),
(2,3)(6,8), (1,2)(6,8),
(1,5)(2,6,3,7,4,8) ] )
gap> Size( norm );
576
Теперь построим в группе a8 элементарную абелеву подгруппу порядка 8, каждая инволюция (т.е. элемент
порядка 2) в которой не имеет неподвижных точек, а затем вычислим ее нормализатор в a8:
gap> elab:= Group( (1,2)(3,4)(5,6)(7,8),
>(1,3)(2,4)(5,7)(6,8),(1,5)(2,6)(3,7)(4,8) );;
gap> Size( elab );
8
gap> IsElementaryAbelian( elab );
true
gap> norm:=Normalizer( a8, AsSubgroup(s8, elab) );
Subgroup( s8, [(5,6)(7,8), (5,7)(6,8), (3,4)(7,8),
(3,5)(4,6), (2,3)(6,7), (1,2)(7,8)])
gap> Size( norm );
1344
Заметим, что группа elab была определена как отдельная группа, поэтому мы воспользовались функцией
AsSubgroup для того, чтобы рассматривать ее как подгруппу в a8. Применение команды
Normalizer(a8,elab); дало бы тот же результат, однако было бы некорректным. В последнем случае
недоступны некоторые эффективные алгоритмы, что может существенно увеличить время расчета.
Еще один пример использования функции AsSubgroup, обращающий внимание на правильное указание
группы, подгруппа которой рассматривается:
gap> IsSubgroup( a8, AsSubgroup( a8, elab ) );
Error, <G> must be a parent group in
18
AsSubgroup( a8, elab ) called from main loop
brk> quit;
gap> IsSubgroup( a8, AsSubgroup( s8, elab ) );
true
Примечание. Нельзя использовать знак "<" вместо IsSubgroup. Так, не приводят к ошибкам команды:
gap> elab < a8;
false
gap> AsSubgroup( s8, elab ) < a8;
false
В данном случае происходит простое сравнение списков элементов указанных групп в соответствии с
лексикографическим порядком. Кроме того, если эти списки еще не вычислены, то они вычисляются в процессе
выполнения операции, что нежелательно при работе с большими группами.
Оператор равенства "=" фактически проверяет равенство групп. Например,
gap> elab = AsSubgroup( s8, elab );
true
означает, что две группы состоят из одинаковых элементов. Заметим, однако, что их свойства могут отличаться, если они
заданы как подгруппы различных групп.
4.5 ФАКТОРГРУППЫ
Теперь вычислим факторгруппу подгруппы norm по подгруппе elab (см. предыдущий параграф). Сначала
зададим elab как подгруппу группы s8:
gap> elab:= AsSubgroup( s8, elab );;
gap> elab.name:= "elab";;
Факторгруппу f получаем следующим образом:
gap> f:= norm / elab;
(Subgroup(s8, [ (5,6)(7,8), (5,7)(6,8), (3,4)(7,8),
(3,5)(4,6), (2,3)(6,7), (1,2)(7,8) ] ) / elab)
gap> Size( f );
168
Полученная группа f, как видно из результата, уже не является группой подстановок. Но операции над ней и
ее элементами производятся аналогично:
gap> Random( f );
FactorGroupElement( elab, (2,8,7)(3,5,6) )
gap> Order( f, last );
3
Построим естественный гомоморфизм из norm на f, отображающий каждый элемент в содержащий его
смежный класс по подгруппе elab.
gap> f.name:= "f";;
gap> hom:= NaturalHomomorphism( norm, f );
NaturalHomomorphism( Subgroup( s8, [ (5,6)(7,8),
(5,7)(6,8), (3,4)(7,8), (3,5)(4,6), (2,3)(6,7),
(1,2)(7,8) ] ), (Subgroup( s8, [ (5,6)(7,8),
(5,7)(6,8), (3,4)(7,8), (3,5)(4,6), (2,3)(6,7),
(1,2)(7,8) ] ) / elab) )
Ядром естественного гомоморфизма является elab:
gap> Kernel( hom ) = elab;
true
Пусть теперь x - произвольный элемент в norm. вычислим сначала его образ, а затем смежный класс, в
котором содержится x, как множество прообразов соответствующего элемента факторгруппы:
gap> x:= Random( norm );
(1,7,5,8,3,6,2)
gap> Image( hom, x );
FactorGroupElement( elab, (2,7,3,4,6,8,5) )
gap> coset:= PreImages( hom, last );
(elab*(2,7,3,4,6,8,5))
gap> IsCoset( coset ); x in coset; coset in f;
true
true
false
Действие группы f на множестве своих элементов с помощью умножения справа приводит к регулярному
представлению группы f подстановками, т.е. к новой группе подстановок.
gap> op:= Operation( f, Elements( f ), OnRight );;
gap> IsPermGroup( op );
true
gap> Maximum( List( op.generators,
19
>
LargestMovedPointPerm ) );
168
gap> IsSimple( op );
true
4.6 КЛАССЫ СОПРЯЖЕННЫХ ЭЛЕМЕНТОВ
Другим источником информации о группе a8 будет являться ее разбиение на классы сопряженых элементов.
Получим список классов сопряженности:
gap> ccl:= ConjugacyClasses( a8 );
[ ConjugacyClass( a8, () ),
ConjugacyClass( a8, (1,3)(2,6)(4,7)(5,8) ),
ConjugacyClass( a8, (1,3)(2,8,5)(6,7) ),
ConjugacyClass( a8, (2,5,8) ),
ConjugacyClass( a8, (1,3)(6,7) ),
ConjugacyClass( a8, (1,3,2,5,4,7,8) ),
ConjugacyClass( a8, (1,5,8,2,7,3,4) ),
ConjugacyClass( a8, (1,5)(2,8,7,4,3,6) ),
ConjugacyClass( a8, (2,7,3)(4,6,8) ),
ConjugacyClass( a8, (1,6)(3,8,5,4) ),
ConjugacyClass( a8, (1,3,5,2)(4,6,8,7) ),
ConjugacyClass( a8, (1,8,6,2,5) ),
ConjugacyClass( a8, (1,7,2,4,3)(5,8,6) ),
ConjugacyClass( a8, (1,2,3,7,4)(5,8,6) ) ]
gap> Length( ccl );
14
Теперь определим порядки представителей классов сопряженности, взяв в каждом классе по одному
представителю:
gap> reps:= List( ccl, Representative );
[ (), (1,3)(2,6)(4,7)(5,8), (1,3)(2,8,5)(6,7),
(2,5,8), (1,3)(6,7), (1,3,2,5,4,7,8),
(1,5,8,2,7,3,4), (1,5)(2,8,7,4,3,6),
(2,7,3)(4,6,8), (1,6)(3,8,5,4),
(1,3,5,2)(4,6,8,7), (1,8,6,2,5),
(1,7,2,4,3)(5,8,6), (1,2,3,7,4)(5,8,6) ]
gap> List( reps, r -> Order( a8, r ) );
[ 1, 2, 6, 3, 2, 7, 7, 6, 3, 4, 4, 5, 15, 15 ]
Определим, сколько элементов содержится в каждом классе:
gap> List( ccl, Size );
[ 1, 105, 1680, 112, 210, 2880, 2880, 3360, 1120,
2520, 1260, 1344, 1344, 1344 ]
Примечание: следует различать функции Order (порядок элемента), Size (порядок группы, класса
сопряженности и т.п.) и Length (длина списка).
Построив классы сопряженных элементов, мы можем рассматривать их функции, т.е. отображения,
принимающие одинаковые значения на всем классе сопряженных элементов. Примером может являться число
неподвижных точек:
gap> nrfixedpoints:= function( perm, support )
> return Number( [1 .. support], x -> x^perm = x);
> end;
function ( perm, support ) ... end
Вычислим его для группы a8:
gap> permchar1:= List(reps, x->nrfixedpoints(x,8));
[ 8, 0, 1, 5, 4, 1, 1, 0, 2, 2, 0, 3, 0, 0 ].
5 СОЗДАНИЕ И ЗАПУСК ПРОГРАММ НА ЯЗЫКЕ GAP
GAP позволяет не только производить вычисления в интерактивном режиме, но и сохранять программы для
дальнейшего их применения. Файлы с программами, которые должны иметь расширение "g", создаются и
редактируются с помощью любого текстового редактора.
Как правило, программа состоит из главной части и набора функций. При чтении программы (с помощью
команды Read) команды, содержащиеся в главной части выполняются непосредственно, а функции только лишь
определяются, и деляют возможным последующее обращение к ним.
При разработке программ в MS Windows удобно одновременно запускать:
- GAP;
- текстовый редактор, в котором открыта разрабатываемая программа;
20
средство просмотра html-файлов (например, Internet Explorer или Netscape Navigator) для чтения
описания GAP в гипертекстовом формате (начальный файл — GAP\HTM\Chapters.html).
Кроме того, набор программ удобно осуществлять на базе файла протокола, создаваемого с помощью
команды LogTo("file.log");.
Пример: составить программу, которая определяет, является ли группа G конечной р-группой для
некоторого р, и возвращает список, первый элемент которого - true или false в зависимости от результата
проверки, а второй - соответствующее значение р, если G — p-группа, и false — иначе.
-
1. Создаем с помощью текстового редактора файл "prog.g" следующего содержания:
Print(" Loading IsFinitePGroup()", "\n");
IsFinitePGroup:=function(G)
local divisors; # список простых делителей
if IsFinite(G)=false then
return [false, false];
else
divisors:=Set(Factors(Size(G)));
if Length(divisors)=1 then
return [true, divisors[1] ];
else
return [false, false];
fi;
fi;
end;;
2. Сохраняем этот файл в каталоге, выбранном с учетом рекомендаций параграфа 1.2.
3. Запустим GAP и определим файл протокола log.txt:
gap> LogTo("log.txt");
Теперь зададим группу диэдра порядка 8:
gap> G:=DihedralGroup(8);
Group( (1,2,3,4), (2,4) )
Попробуем обратиться к функции из файла prog.g:
gap> IsFinitePGroup(G);
Error, Variable: 'IsFinitePGroup' must have a value
Ошибка вызвана тем, что для использования функции этот файл сначала необходимо прочитать. При этом,
если он содержит синтаксические ошибки, то будут выданы сообщения о них. Чтение производится командой
Read:
gap> Read("prog.g");
Loading IsFinitePGroup()
Ошибки обнаружены не были. Было выдано сообщение, включенное для удобства в файл prog.g.
Теперь проверим работу программы для группы диэдра порядка 8, а также для симметрической группы S8.
gap> IsFinitePGroup(G);
[ true, 2 ]
gap> H:=SymmetricGroup(8);
Group( (1,8), (2,8), (3,8), (4,8), (5,8), (6,8), (7,8) )
gap> IsFinitePGroup(H);
[ false, false ]
Очевидно, что программа работает корректно.
21
СПИСОК РЕКОМЕНДУЕМОЙ ЛИТЕРАТУРЫ
1.
2.
3.
4.
5.
6.
Martin Schoenert et. al. GAP. — Lehrstuhl D für Mathematik, RWTH, Aachen. — fifth edition (1995).
Ван дер Варден Б.Л. Алгебра. — М., Наука, 1976. — 623 с.
Каргаполов М.И., Мерзляков Ю.И. Основы теории групп. — М., Наука, 1982. — 288 с.
Кострикин А.И. Введение в алгебру. — М., Наука, 1977. — 495 с.
Курош А.Г. Теория групп. — М., Наука, 1967. — 648 с.
Холл М. Теория групп. — М., Издательство иностранной литературы, 1962. — 468 с.
22
ПРИЛОЖЕНИЕ
Некоторые функции GAP для работы с группами
g * h
g / h
g ^ h
g ^ i
list * g
g * list
list / g
Comm( g, h )
LeftNormedComm( g1, ..., gn )
RightNormedComm( g1,..., gn )
IsGroup( obj )
IsGroupElement( obj )
Order( G, g )
Subgroup( G, L )
AsSubgroup( G, U )
Agemo( G, p )
Centralizer( G, x )
Centralizer( G, U )
Centre( G )
Closure( U, g )
Closure( U, S )
CommutatorSubgroup( G, H )
ConjugateSubgroup( U, g )
DerivedSubgroup( G )
FittingSubgroup( G )
FrattiniSubgroup( G )
Normalizer( S, U )
SylowSubgroup( G, p )
TrivialSubgroup( U )
FactorGroup( G, N )
FactorGroupElement( N, g )
CommutatorFactorGroup( G )
DerivedSeries( G )
LowerCentralSeries( G )
UpperCentralSeries( G )
AbelianInvariants( G )
Exponent( G )
Index( G, U )
IsAbelian( G )
IsCyclic( G )
IsNilpotent( G )
IsElementaryAbelian( G )
IsConjugate( G, x, y )
IsNormal( G, U )
IsSimple( G )
IsSolvable( G )
IsSubgroup( G, U )
GroupId( G )
ConjugacyClasses( G )
ConjugacyClass( G, g )
NormalSubgroups( G )
Elements( G )
произведение элементов g и h
произведение элементов g и h-1
вычисление h-1gh (g,h - элементы группы)
вычисление i-й степени элемента g (i - целое)
умножение списка на элемент g справа
умножение списка на элемент g слева
умножение списка на элемент g-1 справа
коммутатор g-1 h-1 g h
левонормированный коммутатор элементов g1, ..., gn
правонормированный коммутатор элементов g1, ..., gn
проверка, является ли obj группой
проверка, является ли obj элементом группы
порядок элемента g в группе G
подгруппа группы G, порожденная списком элементов L
подгруппа группы G, порожденная порождающими элементами ранее
независимо созданной группы U (если они лежат в G)
подгруппа, порожденную р-ми степенями элементов p-группы G
централизатор элемента x в группе G
централизатор группы U в группе G
центр группы G
подгруппа, порожденная подгруппой U и элементом g
подгруппа, порожденная подгруппами U и S
коммутатор подгрупп G и H
подгруппа, сопряженная с подгруппой U с помощью элемента g
коммутант группы G
подгруппа Фиттинга группы G
подгруппа Фраттини группы G
нормализатор подгруппы U в подгруппе S.
силовская р-подгруппа конечной группы G
тривиальная подгруппа группы U
факторгруппа группы G по нормальной подгруппе N (то же, что G/N)
смежный класс N*g как элемента факторгруппы G/N
(не проверяет нормальность N в G !)
факторгруппа группы G по ее коммутанту
ряда коммутантов группы G
нижний центральный ряд группы G
верхний центральный ряд группы G
инварианты абелевой группы G (если G - неабелева - инварианты
факторгруппы группы G по ее коммутанту)
показатель (экспонента) группы G
индекс подгруппы U в группе G
проверка, является ли группа G абелевой
проверка, является ли группа G циклической
проверка, является ли группа G нильпотентной
проверка, является ли G элементарной абелевой
проверка, сопряжены ли x и y в группе G
проверка, нормально ли U в группе G
проверка, является ли группа G простой
проверка, является ли группа G разрешимой
проверка, является ли U подгруппой группы G
идентификация группы
классы сопряженных элементов группы G
класс сопряженности, содержащий элемент g
список нормальных подгрупп группы G
список элементов группы G
23
Download