GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "longtools.h"2#include "matrix.h"3#include "sort.h"45/**************************************************************************\6@---------------------------------------------------------------------------7@---------------------------------------------------------------------------8@ FILE: orbit_alg.c9@---------------------------------------------------------------------------10@---------------------------------------------------------------------------11@12\**************************************************************************/131415/**************************************************************************\16@---------------------------------------------------------------------------17@ matrix_TYP **orbit_alg(M, G, S, option, length)18@ bravais_TYP *G, *S;19@ matrix_TYP *M;20@ int *option, *length;21@22@ 'orbit_alg calculates the orbit of the matrix M under the group G.23@24@ The length of the orbit is returned by the pointer 'length'.25@ It is possible to calculate the stabiliser of M in G.26@ It is returned in the pointer 'S' which has to be allocated as '*bravais_TYP'27@ before calling the function.28@29@ 'option' is an array of size 5.30@ The following options are possible:31@32@ option[0] = 0: the group operates from the left: x->gx33@ option[0] = 1: the group operates from the right: x->xg34@ option[0] = 2: the group operates via x-> g x g^(tr) (from the left)35@ option[0] = 3: the group operates via x-> g^(tr) x g (from the right)36@ option[0] = 4: the group operates by conjugation: x-> g x g^(-1)37@ (from the left)38@ option[0] = 5: the group operates by conjugation: x-> g^(-1) x g39@ (from the right)40@41@ option[1] = 1: the group operates on the pairs {M, -M}42@ option[1] = 2: the group caluluates the orbit of the set of rows of M;43@ option[1] = 3: combination of 1 and 2.44@ option[1] = 4: the group operates on sublattices of Z^n.45@46@ option[2] = 0: the whole orbit is calculated47@ option[2] = n: only the first n elements of the orbit are calculated48@49@ option[3] = 1: the stabiliser is calculated.50@51@ option[4] = 0: the full stabiliser is calculated.52@ option[4] = n: only the first n elements of the stabiliser are calculated53@ option[4] = -n: only the first n elements of the stabiliser are calculated,54@ afterwards the algorithm is stopped.55@56@ option[5] = 1: Also the inverse of the generators are used in the algorithmn.57@58@---------------------------------------------------------------------------59@60\**************************************************************************/6162/*****************************************63orbit_alg bestimmt die Bahn der Matrix M unter der Gruppe G6465Die Bahnlaenge wird ueber den Zeiger length zurueckgegeben.66Soll der Stabilisator von M in G berechnet werden, so muessen67die Inversen der Erzeuger von G in Ginv angegeben werden.68In diesem Fall wird der Stabilisator ueber den Zeiger S zurueckgegeben.69Der Zeiger S muss aber bereits als *bravais_TYP allokiert sein.7071option ist ein array der Groesse 5.72Folgende Optionen sind moeglich:7374option[0] = 0: die Gruppe operiert durch Linksmultiplikation: x->gx75option[0] = 1: die Gruppe operiert durch Rechtsmultiplikation: x->xg76option[0] = 2: die Gruppe operiert durch x-> g x g^(tr) (von links)77option[0] = 3: die Gruppe operiert durch x-> g^{tr} x g (von rechts)78option[0] = 4: die Gruppe operiert durch Konjugationation: x-> g x g^(-1)79(von links)80option[0] = 5: die Gruppe operiert durch Konjugationation: x-> g^(-1) x g81(von rechts)8283option[1] = 1: die Gruppe operiert auf den Paaren {M, -M}84option[1] = 2: die Gruppe berechnet die Bahn der Menge der Zeilen von M;85option[1] = 3: Kombination von 1 und 2.86option[1] = 4: die Gruppe operiert auf Teilgittern von Z^n.8788option[2] = 0: die volle Bahn wird berechnet89option[2] = n: die ersten n Elemente der Bahn werden berechnet9091option[3] = 1: der Stabilisator wird berechnet9293option[4] = 0: der volle Stabilisator wird berechnet94option[4] = n: die ersten n Elemente des Stabilisators werden berechnet95option[4] = -n: die ersten n Elemente des Stabilisators werden berechnet,96dannach wird der Algorthmus abgebrochen.9798option[5] = 1: Auch die Inversen der Erzeuger werden im Algorithmus99angewendet.100******************************************/101102103static matrix_TYP **Erz;104static matrix_TYP **Erz_inv;105static int *orbit_opt;106static matrix_TYP *hash_mat;107static int hash_prime = 130003;108109110static void matrix_speichern(mat, L, listsize, anz)111matrix_TYP *mat;112matrix_TYP ***L;113int *listsize, *anz;114{115int i, j, k;116117extern matrix_TYP *init_mat();118if((*anz) == 0)119if ((*L=(matrix_TYP **)malloc((*listsize)*sizeof(matrix_TYP *)))==NULL)120{121fprintf (stderr, "malloc failed\n");122exit (2);123}124if ((*anz) >= (*listsize))125{126*listsize += EXT_SIZE;127if ((*L=(matrix_TYP **)realloc(*L,(*listsize)*sizeof(matrix_TYP *)))==NULL)128{129fprintf (stderr, "realloc failed\n");130exit (2);131}132}133(*L)[(*anz)] = mat;134(*anz) ++;135}136137138139static struct baum *addbaum(mat, L, anz, verz, schonda)140matrix_TYP *mat;141matrix_TYP **L;142int anz;143struct baum *verz;144int *schonda;145{146int vergleich;147*schonda = -1;148if(verz == NULL)149{150verz = (struct baum *) malloc(sizeof(struct baum));151verz->no = anz;152verz->left = verz->right = NULL;153}154else155{156vergleich = mat_comp(mat, L[verz->no]);157if(vergleich<0)158verz->left = addbaum(mat, L, anz, verz->left, schonda);159if(vergleich > 0)160verz->right = addbaum(mat, L, anz, verz->right, schonda);161if(vergleich == 0)162*schonda = verz->no;163}164return(verz);165}166167168struct baum *hash_addbaum(mat, L, anz, verz, schonda, hashnumber, hashverz)169matrix_TYP *mat;170matrix_TYP **L;171int anz;172struct baum *verz;173int *schonda, hashnumber, *hashverz;174{175int vergleich;176*schonda = -1;177if(verz == NULL)178{179verz = (struct baum *) malloc(sizeof(struct baum));180verz->no = anz;181verz->left = verz->right = NULL;182}183else184{185if(hashnumber != hashverz[verz->no])186{187if(hashnumber < hashverz[verz->no])188verz->left = hash_addbaum(mat, L, anz, verz->left, schonda, hashnumber, hashverz);189else190verz->right = hash_addbaum(mat, L, anz, verz->right, schonda, hashnumber, hashverz);191}192else193{194vergleich = mat_comp(mat, L[verz->no]);195if(vergleich<0)196verz->left = hash_addbaum(mat, L, anz, verz->left, schonda, hashnumber, hashverz);197if(vergleich > 0)198verz->right = hash_addbaum(mat, L, anz, verz->right, schonda, hashnumber, hashverz);199if(vergleich == 0)200*schonda = verz->no;201}202}203return(verz);204}205206207208209int *make_orbit_options()210{211int *option;212213option = (int *)malloc(6 *sizeof(int));214option[0] = 0;215if(is_option('l') == TRUE)216option[0] = 0;217if(is_option('r') == TRUE)218option[0] = 1;219if(is_option('t') == TRUE)220option[0] = 2;221if(is_option('t') == TRUE && is_option('r') == TRUE)222option[0] = 3;223if(is_option('k') == TRUE)224option[0] = 4;225if(is_option('k') == TRUE && is_option('r') == TRUE)226option[0] = 5;227228option[1] = 0;229if(is_option('p') == TRUE)230option[1] = 1;231if(is_option('u') == TRUE)232option[1] = 2;233if(is_option('p') == TRUE && is_option('u') == TRUE)234option[1] = 3;235if(is_option('g') == TRUE)236option[1] = 4;237238option[2] = optionnumber('L');239option[3] = is_option('S');240option[4] = optionnumber('S');241if (option[4] == -1) option[4] = 0;242option[5] = is_option('i');243return(option);244}245246static void qswap (mat, k, l)247matrix_TYP *mat;248int k,l;249{ int *temp;250251temp = mat->array.SZ[k];252mat->array.SZ[k] = mat->array.SZ[l];253mat->array.SZ[l] = temp;254temp = NULL;255}256257258259260static void orbit_qsort (mat, left, right, orbit_comp)261matrix_TYP *mat;262int left, right;263int (*orbit_comp)();264{265int i, last;266void qswap ();267268if ( left >= right )269return;270qswap (mat, left, (left + right) / 2);271last = left;272for ( i = left+1;273i <= right ;274i ++ )275if ( (*orbit_comp)(mat, i, left) < 0 )276qswap (mat, ++last, i);277qswap (mat, left, last);278orbit_qsort (mat, left, last - 1, orbit_comp);279orbit_qsort (mat, last + 1, right, orbit_comp);280}281282static int orbit_comp (mat, k, l)283matrix_TYP *mat;284int k,l;285{ int i;286int **M;287int cM;288289M = mat->array.SZ;290cM = mat->cols;291for ( i = 0 ; i<cM; i++)292{293if( M[k][i] > M[l][i])294return (-1);295else296if( M[k][i] < M[l][i])297return (1);298}299return (0);300}301302303304static void standartisieren(mat)305matrix_TYP *mat;306{307int i,308j,309k;310311if(orbit_opt[1] == 3)312{313for(i=0; i<mat->rows; i++)314{315k=0;316while(k<mat->cols && mat->array.SZ[i][k] == 0)317k++;318if(k<mat->cols && mat->array.SZ[i][k] <0)319{320for(j=k; j<mat->cols; j++)321mat->array.SZ[i][j] = -mat->array.SZ[i][j];322}323}324}325if(orbit_opt[1] == 1)326{327k = 0; i = 0;328while(i<mat->rows && k == 0)329{330j=0;331while(j<mat->cols && k==0)332{333if(mat->array.SZ[i][j] < 0)334k= -1;335if(mat->array.SZ[i][j] > 0)336k= 1;337j++;338}339i++;340}341if(k == -1)342{343for(i=0;i<mat->rows;i++)344for(j=0;j<mat->cols;j++)345mat->array.SZ[i][j] = -mat->array.SZ[i][j];346}347}348if(orbit_opt[1] == 2 || orbit_opt[1] == 3)349orbit_qsort(mat, 0, mat->rows-1, orbit_comp);350if(orbit_opt[1] == 4)351{352if(orbit_opt[0] == 0 || orbit_opt[0] == 2 || orbit_opt[0] == 4){353long_col_hnf(mat);354}355if(orbit_opt[0] == 1 || orbit_opt[0] == 3 || orbit_opt[0] == 5)356long_row_hnf(mat);357}358}359360361static matrix_TYP *tr_mul(A, B)362matrix_TYP *A, *B;363{364int i, j, k;365matrix_TYP *erg;366367extern matrix_TYP *init_mat();368erg = init_mat(A->rows, B->rows, "");369for(i=0; i<erg->rows; i++)370{371for(j=0; j<erg->cols; j++)372{373erg->array.SZ[i][j] = 0;374for(k=0; k<A->cols; k++)375erg->array.SZ[i][j] += A->array.SZ[i][k] * B->array.SZ[j][k];376}377}378erg->kgv = A->kgv *B->kgv;379return(erg);380}381382static matrix_TYP *grp_mul(A,B)383matrix_TYP *A, *B;384{385matrix_TYP *erg;386extern matrix_TYP *mat_mul();387if(orbit_opt[0] == 0 || orbit_opt[0] == 2 || orbit_opt[0] == 4)388erg = mat_mul(B,A);389if(orbit_opt[0] == 1 || orbit_opt[0] == 3 || orbit_opt[0] == 5)390erg = mat_mul(A,B);391return(erg);392}393394static matrix_TYP *operation(M, i)395matrix_TYP *M;396int i;397{398matrix_TYP *erg, *waste, *waste1;399400extern matrix_TYP *mat_mul();401extern matrix_TYP *tr_mul();402403if(orbit_opt[0] == 0)404erg = mat_mul(Erz[i], M);405if(orbit_opt[0] == 1)406erg = mat_mul(M, Erz[i]);407if(orbit_opt[0] == 2)408{409waste = tr_mul(M, Erz[i]);410erg = mat_mul(Erz[i], waste);411free_mat(waste);412}413if(orbit_opt[0] == 3)414{415waste = tr_pose(Erz[i]);416waste1 = mat_mul(M, Erz[i]);417erg = mat_mul(waste, waste1);418free_mat(waste); free_mat(waste1);419}420if(orbit_opt[0] == 4)421{422waste = mat_mul(Erz[i], M);423erg = mat_mul(waste ,Erz_inv[i]);424free_mat(waste);425}426if(orbit_opt[0] == 5)427{428waste = mat_mul(Erz_inv[i], M);429erg = mat_mul(waste ,Erz[i]);430free_mat(waste);431}432return(erg);433}434435static void make_hash_mat(M)436matrix_TYP *M;437{438int i,j;439extern matrix_TYP *init_mat();440441hash_mat = init_mat(M->rows, M->cols, "");442for(i=0; i<M->rows;i++)443for(j=0;j<M->cols;j++)444{445hash_mat->array.SZ[i][j] = rand();446hash_mat->array.SZ[i][j] %= 1301;447}448}449450451static int hash_number(M)452matrix_TYP *M;453{454int i,j,h;455h = 0;456for(i=0;i<M->rows;i++)457for(j=0;j<M->cols;j++)458h = (h + M->array.SZ[i][j] * hash_mat->array.SZ[i][j])%hash_prime;459return(h);460}461462extern void free_baum(struct baum *p)463{464465if (p!= NULL){466if (p->left != NULL){467free_baum(p->left);468}469if (p->right != NULL){470free_baum(p->right);471}472free(p);473}474475476return;477}478479matrix_TYP **orbit_alg(M, G, S, option, length)480bravais_TYP *G, *S;481matrix_TYP *M;482int *option, *length;483{484int i,j,k;485matrix_TYP **erg;486matrix_TYP **hist, **histinv;487matrix_TYP *I, *A, *K1, *K2;488int *hashnumbers;489int h, *hashverz;490int ergsize, histsize, histinvsize, Ssize;491int erganz, histanz, histinvanz;492int schonda, sch, abbruch;493int num, erzj, erz_anz;494int sopt;495struct baum *Sverz;496struct baum *ergverz;497498extern matrix_TYP *init_mat();499extern matrix_TYP *mat_inv();500extern matrix_TYP *einheitsmatrix();501extern void matrix_speichern();502503ergsize = 0;504histsize = 0;505histinvsize = 0;506erganz = 0;507histanz = 0;508histinvanz = 0;509Ssize = 0;510ergverz = NULL;511Sverz = NULL;512orbit_opt = option;513erzj = 0;514if(orbit_opt[5] == 1)515erz_anz = 2 * G->gen_no;516else517erz_anz = G->gen_no;518Erz = (matrix_TYP **) malloc(erz_anz *sizeof(matrix_TYP *));519for(i=0;i< G->gen_no;i++)520Erz[i] = G->gen[i];521if(orbit_opt[5] == 1)522{523for(i=0;i<G->gen_no;i++)524Erz[G->gen_no + i] = mat_inv(G->gen[i]);525}526if(orbit_opt[3] == TRUE || orbit_opt[0] == 4 || orbit_opt[0] == 5)527{528Erz_inv = (matrix_TYP **) malloc(erz_anz *sizeof(matrix_TYP *));529for(i=0;i<erz_anz;i++)530Erz_inv[i] = mat_inv(Erz[i]);531}532make_hash_mat(M);533534535standartisieren(M);536h = hash_number(M);537ergverz = hash_addbaum(M, erg, erganz, ergverz, &schonda, h, NULL);538erg = (matrix_TYP **)malloc(EXT_SIZE *sizeof(matrix_TYP));539erg[0] = init_mat(M->rows, M->cols, "");540hashverz = (int *)malloc(EXT_SIZE *sizeof(int));541hashverz[0] = h;542for(i=0; i<M->rows; i++)543for(j=0; j<M->cols; j++)544erg[0]->array.SZ[i][j] = M->array.SZ[i][j];545erg[0]->kgv = M->kgv;546erganz = 1;547ergsize = 100;548if(orbit_opt[3] == 1)549{550I = einheitsmatrix(Erz[0]->cols);551matrix_speichern(I, &hist, &histsize, &histanz);552matrix_speichern(I, &histinv, &histinvsize, &histinvanz);553S->gen_no = 0;554S->dim = Erz[0]->cols;555}556sopt = orbit_opt[3];557558abbruch = FALSE;559num = 0;560while(abbruch == FALSE)561{562for(erzj=0; erzj<erz_anz && abbruch == FALSE; erzj++)563{564A = operation(erg[num], erzj);565standartisieren(A);566h = hash_number(A);567ergverz = hash_addbaum(A, erg, erganz, ergverz, &schonda, h, hashverz);568if(schonda != -1 && sopt == TRUE)569{570K1 = grp_mul(hist[num], Erz[erzj]);571K2 = grp_mul(K1, histinv[schonda]);572if(mat_comp(K2, I) != 0)573{574Sverz = addbaum(K2, S->gen, S->gen_no, Sverz, &sch);575if(sch == -1)576matrix_speichern(K2, &S->gen, &Ssize, &S->gen_no);577}578else{579/* inserted this case on 21 Oct 98 tilman */580free_mat(K2);581K2 = NULL;582}583if ((schonda == -1 || (schonda != -1 && sch != -1)) && K2 != NULL)584free_mat(K2);585free_mat(K1); K2 = NULL;586}587if(schonda == -1)588{589if(erganz == ergsize)590{591if((hashverz = (int *)realloc(hashverz, (ergsize+EXT_SIZE)*sizeof(int))) == NULL)592{593printf("realloc failed\n");594exit(2);595}596}597hashverz[erganz] = h;598matrix_speichern(A, &erg, &ergsize, &erganz);599A = NULL;600if(sopt == TRUE)601{602K1 = grp_mul(hist[num], Erz[erzj]);603matrix_speichern(K1, &hist, &histsize, &histanz);604K1 = NULL;605K1 = grp_mul(Erz_inv[erzj], histinv[num]);606matrix_speichern(K1, &histinv, &histinvsize, &histinvanz);607K1 = NULL;608}609}610if(schonda != -1)611free_mat(A);612if(orbit_opt[2] > 0 && erganz == orbit_opt[2])613abbruch = TRUE;614if(orbit_opt[4] <0 && -orbit_opt[4] == S->gen_no)615abbruch = TRUE;616if(orbit_opt[4] > 0 && orbit_opt[4] == S->gen_no)617sopt = FALSE;618}619num++;620if(num == erganz)621abbruch = TRUE;622}623*length = erganz;624if(orbit_opt[3] == TRUE)625{626for(i=1; i<histanz; i++)627{628free_mat(hist[i]);629free_mat(histinv[i]);630}631free(hist); free(histinv);632free_mat(I);633}634635/* changed tilman 11/3/97 from636if(orbit_opt[3] == TRUE || orbit_opt[0] == 3)637to : */638if(orbit_opt[3] == TRUE || orbit_opt[0] == 4)639{640for(i=0;i<erz_anz;i++)641free_mat(Erz_inv[i]);642free(Erz_inv);643}644if(orbit_opt[5] == 1)645{646for(i=0;i<G->gen_no;i++)647free_mat(Erz[G->gen_no + i]);648}649free(Erz);650free_mat(hash_mat);651652/* inserted 16/1/07 tilman */653free(hashverz);654free_baum(ergverz);655free_baum(Sverz);656657/* inserted 16/07/97 tilman */658for (i=0;i<length[0];i++)659Check_mat(erg[i]);660661return(erg);662}663664665666