Maria Donten 03.02.2009 Macierze symetryczne i nasycone grupy permutacji projekt w ramach laboratorium programowania w logice 1 Wstęp Główny cel projektu to napisanie programu, pomagającego wyznaczyć nasycone podgrupy grupy permutacji i odpowiadające im przestrzenie punktów stałych przy ustalonym działaniu na przestrzeni macierzy. Matematyczne podstawy zagadnienia są omówione (szkicowo) w części 2. Ze względu na to, że program ma stanowić narzędzie pomocne przy obliczeniach algebraicznych, ma charakter raczej biblioteki niż aplikacji. Ale najważniejsze obliczenia zostały zapisane w postaci kilku predykatów, omówionych w części 3 dokumentu działanie tych predykatów przede wszystkim warto obejrzeć przy sprawdzaniu programu. Program był testowany i działa pod SICStus Prologiem 4.0.4, zainstalowanym w Laboratorium Komputerowym WMIM oraz pod SWI-Prologiem 5.6.62 (pod Windows XP). Ze względów praktycznych więcej testów zostało zrobionych pod SWI-Prologiem, ale wygląda na to, że pod SICStus Prologiem też wszystko działa tak, jak powinno. 2 Opis projektu 2.1 Problem Rozpatrujemy działanie ρ dowolnej podgrupy G grupy S n permutacji zbioru {1,..., n} na przestrzeni M n wszystkich symetrycznych macierzy kwadratowych o wymiarze n o współrzędnych z dowolnego ciała. Działanie ρ jest zdefiniowane następująco: ρ(g)(m) = A 1 g MA g. Przez A g oznaczamy macierz permutacji g, czyli macierz, która w polu (i, j) ma 1, jeśli permutacja g przeprowadza i na j, a w przeciwnym przypadku 0. W dalszym ciągu, pisząc o działaniu grupy permutacji na M n, odnosimy się zawsze do tego działania. Inaczej można je opisać w ten sposób, że permutacja g mówi, jak przestawić wiersze i kolumny danej macierzy, żeby otrzymać wynikową macierz. Interesują nas wyłącznie tranzytywne podgrupy G < S n, dalej zawsze będę zakładać, że G spełnia ten warunek (czyli każdą liczbę ze zbioru {1,..., n} można przeprowadzić na dowolną liczbę z tego zbioru za pomocą pewnej permutacji z G). 1
W związku z badaniem pewnych modeli drzew filogenetycznych interesują nas podprzestrzenie liniowe M n złożone z punktów stałych tego działania (dla różnych G < S n ). Łatwo policzyć, że jeśli macierz M = (m i,j ) 1 i,j n jest punktem stałym przekształcenia ρ(g) odpowiadającego wybranej permutacji g, to jej współrzędne spełniają warunek m i,j = m g(i),g(j). Wobec tego, żeby opisać przestrzeń punktów stałych zdefiniowanego powyżej działania pewnej grupy G < S n, wystarczy powiedzieć, które pola macierzy mają być równe. Stąd można wziąć pomysł na zwięzły sposób opisu takiej podprzestrzeni. Będziemy je reprezentować za pomocą macierzy wypełnionej liczbami z przedziału {0,..., k} (wszystkie te liczby pojawiają się w macierzy). Pola m i,j = m s,t tej macierzy są równe wtedy i tylko wtedy, gdy ta równość musi zachodzić w każdej macierzy będącej punktem stałym rozpatrywanej grupy G. Przykład. Dla grupy G = (1)(2)(3, 4), (1, 3)(2, 4) przestrzeń punktów stałych jest opisywana macierzą 0 1 2 2 1 0 2 2 2 2 0 1. 2 2 1 0 Wymiar tej przestrzeni wynosi 3 (ogólnie: k + 1), a jej (przykładową) bazą są macierze 1 0 0 0 0 1 0 0 0 0 1 0, 0 0 0 1 0 1 0 0 1 0 0 0 0 0 0 1, 0 0 1 0 0 0 1 1 0 0 1 1 1 1 0 0. 1 1 0 0 Z drugiej strony chcielibyśmy dla danej podprzestrzeni liniowej L M n chcielibyśmy umieć znaleźć wszystkie macierze, które będą zachowywały punkty tej podprzestrzeni przy opisanym powyżej działaniu. Łatwo sprawdzić, że tworzą one grupę. Podgrupę G < S n nazwiemy nasyconą, jeśli jest maksymalną podgrupą zachowującą wszystkie punkty swojej przestrzeni punktów stałych. Można powiedzieć, że grupy nasycone to maksymalne podgrupy S n zachowujące pewne podprzestrzenie M n. Chcielibyśmy umieć wyznaczać grupy nasycone i ich przestrzenie punktów stałych, przynajmniej dla niedużych wartości n, żeby spróbować zrozumieć te obiekty i umieć coś o nich udowodnić. Do tej pory za pomocą pakietu GAP przeznaczonego do obliczeń algebraicznych udało się wyznaczyć grupy nasycone dla 1 n 9 (dalej programy były zbyt mało efektywne). 2.2 Zapis w Prologu Pisząc ten program w Prologu chciałam sprawdzić, czy łatwość wyrażania pewnych własności opisanych powyżej obiektów w tym języku pomoże poprawić efektywność obliczeń. Niestety, dość szybko udało się napisać program, który wyrażał odpowiednie własności, 2
ale działał zdecydowanie zbyt wolno. Po wielu modyfikacjach, które poprawiły efektywność, ale za to zmniejszyły elegancję zapisu, program potrafi policzyć dość szybko grupy nasycone do wymiaru 6 włącznie. W wymiarze 7 bardzo długo nie widać żadnego efektu powodem tego jest brak grup nasyconych w sprawdzanych przez program w pierwszej kolejności przypadkach. Natomiast w wymiarze 8 w ciągu kilku minut od uruchomienia pojawiają się pierwsze wyniki, ale potem oczekiwanie na następne trwa bardzo długo. Wyższych wymiarów nie badałam. Ponieważ to nie jest dokumentacja techniczna, nie będę omawiała szczegółowo budowy programu ograniczę się jedynie do krótkiego opisu drogi, która prowadzi do wyznaczenia grup nasyconych. Chociaż program właściwie jest biblioteką, nie udostępniam również dokumentacji, jaką powinien otrzymać użytkownik biblioteki, ponieważ i tak nikt nie będzie z tego korzystał (a zresztą większość predykatów jest opisana za pomocą komentarzy do kodu). Poszukiwanie grup nasyconych rozpoczynamy od wyznaczenia pewnego (stosunkowo niedużego) zbioru macierzy, które mogą opisywać przestrzeń punktów stałych pewnej grupy (jak w przykładzie w punkcie 2.1). Taka macierz musi spełniać następujące warunki: 1. jest symetryczna (bo M n to macierze symetryczne), 2. ma wszystkie wyrazy na przekątnej równe (bo G jest tranzytywna), i różne od wszystkich innych, 3. w każdym wierszu i w każdej kolumnie jest tyle samo wystąpień każdej liczby (z definicji rozpatrywanego działania, a właściwie jej przeformułowania); inaczej mówiąc, każdy wiersz macierzy jest permutacją pierwszego, z symetrii kolumny również spełniają ten warunek. Macierzy spełniających pierwsze dwa warunki, opisywanych przez predykat symmat(wymiar, Macierz), jest na tyle niedużo, jeśli nie są do końca ustalone, żeby badać je dalej. Dla nich sprawdzamy trzeci warunek, dokonując przy tym ustalenia jeszcze nie ustalonych pól macierzy (na różne sposoby) predykat nicemat2(wymiar, Macierz). Te macierze są już na tyle ładne, że chcemy dla nich wyznaczyć wszystkie permutacje, które je zachowują predykat perminv(permutacja, Wymiar, Macierz). A potem wystarczy sprawdzić, jak wygląda macierz opisująca podprzestrzeń macierzy zachowywanych przez te permutacje (predykat maxgimat(grupa, Wymiar, Macierz)) i porównać ją z wyjściową macierzą. Jeśli wyjdą równe, to grupa jest nasycona. Te wszystkie sprawdzenia są wykonywane przy pomocy predykatu invmat(wymiar, Grupa), który dodatkowo próbuje rozpoznać, z jaką znaną grupą G jest izomorficzna. 3 Co warto zobaczyć Powyżej opisany jest pomysł projektu, jego źródła matematyczne i szkic postępowania programistki. W tej części wyszczególniamy predykaty, które warto zobaczyć, zapoznając się z działaniem programu. Ich znaczenie deklaratywne oraz sposoby reprezentacji używanych danych są dokładniej opisane w komentarzach do kodu. 3
3.1 Główny cel projektu Przede wszystkim główne obliczenia można obejrzeć, wywołując predykat invmat2(n, G), gdzie N jest liczbą ze zbioru {2,..., 6} (dla 1 nie działa to nie ma znaczenia, a tak było łatwiej napisać część programu). Dla N = 8 można doczekać się pewnych wyników (na moim komputerze; na wydziałowych chyba też), dla N = 7 może to potrwać bardzo długo... Argument G to grupa permutacji, powinien być nieustalony. Wersja invmat2(n, G) wypisuje ładnie wszystkie permutacje z grupy G; wersja invmat(n, G) tego nie robi, a invmat(n, G, M) dodatkowo ma argument odpowiadający macierzy opisującej podprzestrzeń punktów stałych grupy G. Wersje predykatu nicemat zwracają macierze, które spełniają trzy warunki z opisane w poprzedniej części. Predykat nicemat2(n, M) dla 2 N 6 i M nieustalonego odnosi sukces dla wszystkich macierzy, które uznał za odpowiednie do dalszego sprawdzania. Korzysta ze zdefiniowanego przeze mnie predykatu permutation2, opisanego w kodzie. Wersja nicemat(n, M) korzysta ze standardowej wersji predykatu permutation, co powoduje problem z wielokrotnymi sukcesami. Wersja nicematprint(n, M) robi to, co nicemat2(n, M) i dodatkowo ładnie wypisuje otrzymane macierze, więc jest najlepsza do testów. Predykat groupinv(g, N, M) sprawdza, czy grupa generowana przez permutacje (zbioru N elementów) z listy G zachowują macierz M. Jeśli wywołamy go z ustalonym G i N, a M zostanie nieustalone, to dostaniemy ogólną (nieustaloną) postać macierzy zachowywanej przez elementy grupy permutacji generowanej przez zbiór G. Uwaga: permutacje w programie są reprezentowane jako listy obrazów kolejnych elementów zbioru {1,..., N}, czyli na przykład permutacji o rozkładzie na cykle (2)(1, 4, 3) odpowiada zapis [4, 2, 1, 3]. Proponuję wywołać na przykład groupinv([[2,1,4,3],[1,2,4,3]], 4, M), printmat(4, M). i obejrzeć, jakie znaczenie dla macierzy ma fakt, że grupa generowana przez podane permutacje nie jest tranzytywna. Dla porównania można sprawdzić wynik dla grupy tranzytywnej groupinv([[2,3,4,1],[2,1,4,3]], 4, M), printmat(4, M). (PrintMat(Wymiar, Macierz) wypisuje macierz w ładnej postaci). Predykat maxgimat(g, N, M) dodatkowo dokonuje ustalenia macierzy (jeśli grupa jest tranzytywna). Można sprawdzić wynik wywołania maxgimat([[2,3,4,1],[2,1,4,3]], 4, M), printmat(4, M). 3.2 Inne ciekawe wyniki Większość programu jest dość szczegółowo opisana w komentarzach do kodu; tutaj wspomnijmy jeszcze tylko o ostatniej części programu, która zawiera predykaty do operacji na permutacjach i grupach permutacji. Powstawała ona pod koniec prac nad programem i niewątpliwie można ją rozszerzyć. W obecnej wersji głównym celem pisania tych predykatów było umożliwienie rozpoznawania pewnych typów grup, tak, żeby program, wyliczając grupę nasyconą, umiał określić, z jaką znaną grupą ona jest izomorficzna. W tym celu program umie mnożyć (składać) permutacje i liczyć ich rząd (jako elementu w grupie). Następnie, korzystając z prezentacji grup (opisu za pomocą generatorów i relacji), albo z innego opisu, rozpoznaje grupę hiperbinarną (Z n 2), symetryczną (czyli pełną grupę 4
permutacji), cykliczną, dihedralną i trywialną (oczywiście). Można przetestować operacje na permutacjach. Z testowaniem rozpoznawania grup jest trudniej (oprócz użycia przez predykat invmat) brakuje predykatu, który wyrażałby konstruktywnie własność bycia grupą generowaną przez dany zbiór permutacji, więc całą grupę do testu trzeba wpisywać ręcznie... W tej części brakuje predykatów, które wyrażałyby własności permutacji reprezentowanych za pomocą rozkładu na cykle, a nie listy obrazów kolejnych liczb to jest możliwe rozszerzenie programu. W ogóle operacje na permutacjach wydały mi się ciekawym kierunkiem rozszerzania tego projektu. 3.3 Uwagi Pewne grupy nasycone (wyniki invmat2) mogą się powtarzać, ponieważ program nie umie rozpoznać, czy grupy są sprzężone w grupie permutacji, lub czy jedną macierz można otrzymać z drugiej przez jednoczesną permutację wierszy i kolumn i ewentualną zmianę oznaczeń pól. To nie powinno być trudne do napisania. Niektóre predykaty w kodzie programu nie są używane w obecnej wersji do wykonywania głównych obliczeń. Zdecydowałam się jednak nie wyrzucać ich z programu, ponieważ mogą być ciekawe, mimo że nie pozwalają na implementację najszybszej jak dotąd wersji. I, jako że program jest właściwie biblioteką, może zawierać różne możliwości wykonywania pewnych operacji. Predykat invmat korzysta z predykatu setof, podającego zbiór wszystkich sukcesów danego predykatu, co do którego nie pamiętam, czy przypadkiem nie był zakazany. Ale bardzo dobrze się nadaje do zebrania wyników działania predykatu, który sprawdza permutacje zachowujące daną macierz, i tworzy z nich listę (grupę), z którą można dalej pracować jako ze strukturą algebraiczną... W pewnym momencie miałam problem z kompatybilnością z SICStus Prologiem (bo większość kodu pisałam na SWI), ale mam nadzieję, że wszystkie używane w obecnej wersji funkcje biblioteczne są zgodne. W każdym razie jeśli coś nie będzie działać, to być może powodem są pewne różnice pomiędzy implementacjami Prologu. 5