GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include <typedef.h>1#include <getput.h>2#include <matrix.h>3#include <sort.h>4#include <bravais.h>5#include <base.h>6#include <longtools.h>7#include <datei.h>8#include <presentation.h>91011extern int INFO_LEVEL;12extern int SFLAG;1314#define DEBUG FALSE151617static matrix_TYP *search_inverse(bahn *s,18matrix_TYP *x)19{2021int i;2223for (i=0;i<s->length;i++)24if (s->representatives[i] == x)25return s->rep_invs[i];2627return (matrix_TYP *) -1;2829} /* search_inverse(...) */30313233static void con_reduce(int *w){3435int i = 1;3637while (i){38if (w[1] == -w[w[0]]){39for (i=1;i<w[0];i++) w[i] = w[i+1];40w[0] -= 2;41}42else{43i = 0;44}45}4647return;4849} /* con_reduce */505152void normalize_word(int *w){5354int i,55j;5657for (i=w[0];i>1;i--){58if (w[i] == -w[i-1]){59for (j=i+1;j<=w[0];j++) w[j-2] = w[j];60w[0] -= 2;61i = w[0] + 1;62}63}6465return;6667} /* normalize_word(int *w) */68697071static void order(int **w,72int *l)73{7475int i,76*P,77good = 1;7879while (good){80good = 0;8182for (i=0;i<l[0]-1;i++){83if (w[i][0] > w[i+1][0]){84P = w[i];85w[i] = w[i+1];86w[i+1] = P;87good = 1;88}89}90}919293return;9495} /* order(...) */9697static int skip_sub_relator(int *w1,int *w2){9899int i,j,n,*wn;100101n = w1[0]/2 + 1;102103for (i=0;i<(w2[0] - n +1);i++){104if (!memcmp(w1+1,w2+1+i,n*sizeof(int))){105wn = (int *) malloc((1+w1[0]+w2[0]) * sizeof(int));106wn[0] = w1[0]+w2[0];107memcpy(wn+1,w2+1,i * sizeof(int));108for (j=1;j<=w1[0];j++)109wn[j+i] = -w1[w1[0] - j + 1];110memcpy(wn+i+1+w1[0],w2+i+1,(w2[0] - i) * sizeof(int));111112normalize_word(wn);113if (wn[0] >= w2[0]){114fprintf(stderr,"error\n");115exit(3);116}117118memcpy(w2,wn,(wn[0] + 1) * sizeof(int));119free(wn);120return TRUE;121}122123}124125return FALSE;126} /* skip_sub_relator(...) */127128129static int skip_sub_relator_inv(int *w1,int *w2){130131int i,132j;133134static int wi[11];135136if (w1[0] > 10) return FALSE;137138for (i=1,j=w1[0] ; i<=w1[0] ; i++,j--)139wi[i] = -w1[j];140wi[0] = w1[0];141142return skip_sub_relator(wi,w2);143144} /* skip_sub_relator_inv(...) */145146147148void simplify_presentation(int **w,149int *l){150int i,151j,152good = 1;153154while (good){155good = 0;156157/* search for trivial relators */158for (i=0;i<l[0];i++){159if (w[i][0] == 0){160free(w[i]);161l[0]--;162w[i] = w[l[0]];163good = 1;164i = l[0] + 1;165}166}167168/* oder the relators according to their length */169order(w,l);170171172/* see if one of the short relators is a subrelator of a longer one */173for (i=0;i<l[0] - 1; i++){174for (j=l[0]-1;j>i ; j--){175if (w[i][0] > 0 &&176w[j][0] > 0){177if(skip_sub_relator(w[i],w[j]) || skip_sub_relator_inv(w[i],w[j]))178good = TRUE;179}180}181}182183for (i=0;i<l[0];i++){184normalize_word(w[i]);185con_reduce(w[i]);186}187188j = 0 ;189for (i=0;i<l[0];j+=w[i][0] , i++);190191if (DEBUG)192fprintf(stderr,"%d relators of total length %d\n",i,j);193194}195196197return;198199} /* simplify_presentation(...) */200201202static int *relator3(int k,203int *w1,204int *w2){205206int i,207j,208*res;209210211res = (int *) calloc( w1[0] + w2[0] + 2, sizeof(int));212res[0] = w1[0] + w2[0] + 1;213214memcpy(res+2,w1+1,w1[0] * sizeof(int));215res[1] = k+1;216217for (i=1,j=res[0];i<=w2[0];j--,i++)218res[j] = -w2[i];219220return res;221222} /* relator3 (....) */223224static int *relator2(int *w1,225int *wz,226int *w2){227228int i,229j,230*res;231232233res = (int *) calloc( w1[0] + w2[0] + wz[0] + 1 , sizeof(int));234res[0] = w1[0] + w2[0] + wz[0];235236memcpy(res+1,w1+1,w1[0] * sizeof(int));237memcpy(res+1+w1[0],wz+1,wz[0] * sizeof(int));238239for (i=1,j=res[0];i<=w2[0];j--,i++)240res[j] = -w2[i];241242return res;243244} /* relator2 (....) */245246247/**************************************************************************248@249@--------------------------------------------------------------------------250@251@ void put_presentation(int **w,252@ int l,253@ bravais_TYP *G,254@ char *O)255@256@257@258@259@--------------------------------------------------------------------------260@261***************************************************************************/262void put_presentation(int **w,263int l,264bravais_TYP *G,265char *O){266267int i;268269270if (strchr(O,'G')){271if (strchr(O,'4')){272printf("F := FreeGroup(%d);\n",G->gen_no);273printf("g := GeneratorsOfGroup(F);");274}275276printf("rel := [\n");277}278279for (i=0;i<l-1;i++){280put_word(w[i],O);281282if (strchr(O,'G')){283printf(",\n");284}285}286287put_word(w[i],O);288if (strchr(O,'G')){289printf("];\n");290}291292293if (strchr(O,'G')){294295printf("G := F/ rel;\n");296297if (strchr(O,'V')){298printf("p := PresentationFpGroup(G);\n");299printf("TzGoGo(p);\n");300printf("G := FpGroupPresentation(p);\n");301}302303if (strchr(O,'S')){304printf("Size(G);\n");305}306307if (strchr(O,'Q')){308printf("quit;\n");309}310}311312return;313314} /* put_presentation(...) */315316317318319static int *get_word_to_generator(bahn *A,320matrix_TYP *h)321{322323int i;324325for (i=0;i<A->length && mat_comp(A->representatives[i],h) ; i++);326327if (i == A->length){328fprintf(stderr,"error\n");329exit(3);330}331332return A->words[i];333334} /* get_word_to_generator */335336337338int *mul_word(int *w1,339int *w2){340341int *w;342343344w = (int *) malloc((w1[0]+w2[0]+1) * sizeof(int));345346w[0] = w1[0]+w2[0];347348memcpy(w+1,w1+1,w1[0]*sizeof(int));349memcpy(w+1+w1[0],w2+1,w2[0]*sizeof(int));350351return w;352353}354355356static int needed(matrix_TYP **VL,357matrix_TYP *x,358matrix_TYP **GEN){359360int i = 0,361j,362k,363RES = FALSE;364365matrix_TYP *y;366367368i=0;369while(VL[i]){370y = mat_mul(x,VL[i]);371372j=0;373while(VL[j] && y){374if (!mat_comp(VL[j],y)){375free_mat(y);376y = NULL;377}378j++;379}380if (y){381VL[j] = y;382RES = TRUE;383}384385i++;386}387388if (RES){389390i=0;391while(GEN[i]) i++;392GEN[i] = x;393394i = 0;395while (VL[i]){396397k = 0;398while(GEN[k]){399y = mat_mul(GEN[k],VL[i]);400401j=0;402while(VL[j] && y){403if (!mat_comp(VL[j],y)){404free_mat(y);405y = NULL;406}407j++;408}409if (y){410VL[j] = y;411}412k++;413}414i++;415}416}417418return RES;419420} /* needed (.....) */421422423/*************************************************************************424@425@-------------------------------------------------------------------------426@427@428@-------------------------------------------------------------------------429@430**************************************************************************/431static void con_relations(bravais_TYP *G,432matrix_TYP **GGENINV,433matrix_TYP **GEN,434matrix_TYP **GENINV,435int **GW,436bahn **s,437int level,438int ***w,439int *l,440int *speicher,441matrix_TYP **GENU,442int **GENUW,443int GENU_NO)444{445446447matrix_TYP **VS,448**GENUH,449*y,450*x;451452453int i,454j,455k,456*w2 = NULL,457*w3,458**GENUWH,459found = GENU_NO;460461462463VS = (matrix_TYP **) calloc(s[level]->length+1,sizeof(matrix_TYP *));464VS[0] = s[level]->orbit[0];465466GENUWH = (int **) malloc((GENU_NO+s[level]->length) * sizeof(int *));467GENUH = (matrix_TYP **) calloc((GENU_NO+s[level]->length),468sizeof(matrix_TYP*));469memcpy(GENUH,GENU,GENU_NO * sizeof(matrix_TYP *));470memcpy(GENUWH,GENUW,GENU_NO * sizeof(int *));471472/* see which conjugate we will need */473for (i=0;i<found;i++){474k = TRUE;475for (j=0;j<s[level]->gen_no && k;j++){476477x = mat_kon(GEN[j],GENUH[i],GENINV[j]);478479if (needed(VS,x,GENUH+GENU_NO)){480GENUWH[found] = relator2(GW[j],GENUWH[i],GW[j]);481482if (DEBUG){483y = mapped_word(GENUWH[found],G->gen,GGENINV);484485if (mat_comp(x,y)){486fprintf(stderr,"error in pres\n");487exit(3);488}489free_mat(y);490}491492found++;493}494else{495free_mat(x);496}497498for (k=0;VS[k];k++);499k = (k==s[level]->length);500501}502}503504505if (DEBUG)506fprintf(stderr,"GENU_NO %d found %d level %d\n",GENU_NO,found,level);507508/* conjugate relations */509for (i=0;i<found;i++){510for (j=0;j<s[level]->gen_no;j++){511512x = mat_kon(GEN[j],GENUH[i],GENINV[j]);513514/* find a word in the generators, and check a bit */515if (!is_element(x,G,s,&w2)){516fprintf(stderr,"error in pres\n");517exit(3);518}519520if (DEBUG){521y = mapped_word(w2,G->gen,GGENINV);522523if (mat_comp(x,y)){524fprintf(stderr,"error in pres\n");525exit(3);526}527free_mat(y);528}529530w3 = relator2(GW[j],GENUWH[i],GW[j]);531532if (DEBUG){533y = mapped_word(w3,G->gen,GGENINV);534535if (mat_comp(x,y)){536fprintf(stderr,"error in pres\n");537exit(3);538}539free_mat(y);540}541542if ( *l == *speicher){543*speicher += 256;544*w = (int **) realloc(*w,*speicher * sizeof(int *));545}546547548k = 0;549w[0][*l] = relator2(&k,w3,w2);550551normalize_word(w[0][*l]);552con_reduce(w[0][*l]);553554if (DEBUG){555y = mapped_word(w[0][*l],G->gen,GGENINV);556Check_mat(y);557if (!y->flags.Diagonal){558fprintf(stderr,"error in pres\n");559exit(3);560}561free_mat(y);562}563564if (w[0][*l][0] == 0){565free(w[0][*l]);566}567else{568/* put_word(w[0][*l],"M"); */569(*l)++;570}571572free(w3);573free(w2); w2 = NULL;574free_mat(x);575}576}577578579for (i=GENU_NO;i<found;i++){580free_mat(GENUH[i]);581free(GENUWH[i]);582}583free(GENUH);584free(GENUWH);585586for (i=1;i<s[level]->length;i++)587if (VS[i]) free_mat(VS[i]);588free(VS);589590return;591592}593594595596matrix_TYP *pres_on_many_generators(bravais_TYP *G,597int *OPT){598599600bravais_TYP *H;601bahn **s;602matrix_TYP **basis;603int i,j;604int k,l;605int zeile;606matrix_TYP *RES;607int MAX = G->gen_no + 2;608int *w;609610s = NULL;611H = copy_bravais(G);612613basis = get_base(H);614615616if (H->gen_no > H->dim){617H->order = red_gen(H,basis,&s,0);618for (i=0;i<H->dim;i++){619free_bahn(s[i]);620free(s[i]);621}622free(s);623}624625s = strong_generators(basis,H,TRUE);626627/* the situation is: H = G as a group, and the generators of H form a subset of the generators of G */628629/* calculate a presentation for H on the generators of H */630RES = pres(s,H,OPT);631632zeile = RES->rows;633real_mat(RES,RES->rows + G->gen_no , RES->cols);634635/* add relations of the form g_i = word(h_j) for those g_i which are not in the generators of H, */636/* but represent the g_i by i+MAX */637/* mathemetically this is an tietze tranformation of the third (?) kind, add a generator */638/* <h_i|rs> \cong <h_i,g| rs,g=w(h_i) > */639for (i=0;i<G->gen_no;i++){640641/* is_element calculates a word such that g_i = w(h_j) */642w = NULL;643if(!is_element(G->gen[i],H,s,&w)){644fprintf(stderr,"error in pres_on_many_generators(...)\n");645exit(3);646}647648if (RES->cols <= w[0]){649real_mat(RES,RES->rows,w[0]+1);650}651652/* the relation is now g_i^(-1) * w(h_J) = 1 */653memcpy(RES->array.SZ[zeile],w,(w[0]+1) * sizeof(int));654RES->array.SZ[zeile][0] = -i - 1 - MAX;655656/* for sanitary reasons remove those relations which look like g_i * g_i^(-1) */657if (w[0] == 1 && w[1] == i+1){658RES->array.SZ[zeile][0] = 0;659RES->array.SZ[zeile][1] = 0;660}661else{662zeile++;663}664665free(w);666}667668if (zeile < RES->rows)669real_mat(RES,zeile,RES->cols);670671672/* translate this presentation in the generators of G */673/* on strange thing : to be able to do this in one go, we represent the j-th generator of G */674/* by the number j+MAX temporaly */675for (i=0; i< H->gen_no ; i++){676677/* search for a j with H->gen[i] == G->gen[j] */678for (j=0; j< G->gen_no && mat_comp(H->gen[i],G->gen[j]) ; j++);679680/* replace every occurence of i+1 or -(i+1) in RES with (j+1)+MAX or -(j+1)-MAX respectively */681for (k=0;k<RES->rows;k++){682for (l=0;l<RES->cols;l++){683if (RES->array.SZ[k][l] == i+1)684RES->array.SZ[k][l] = j + 1 + MAX;685else if (RES->array.SZ[k][l] == -i-1)686RES->array.SZ[k][l] = -j - 1 - MAX;687}688}689}690691/* now RES contains relations for G with the strange thing that the number j generator has been692replaced with the generator j+MAX temporaly if it is also a generator of H */693for (k=0;k<RES->rows;k++){694for (l=0;l<RES->cols;l++){695if (RES->array.SZ[k][l] > MAX)696RES->array.SZ[k][l] -= MAX;697else if (RES->array.SZ[k][l] < -MAX)698RES->array.SZ[k][l] += MAX;699}700}701702703704/* clean up */705for (i=0;i<H->dim;i++){706free_mat(basis[i]);707free_bahn(s[i]);708free(s[i]);709}710free(basis);711free(s);712free_bravais(H);713714return RES;715716717} /* pres_on_many_generators(...) */718719720/************************************************************************721@722@------------------------------------------------------------------------723@724@ matrix_TYP *pres(bahn **s,725@ bravais_TYP *G,726@ int *OPT)727@728@729@730@------------------------------------------------------------------------731@732*************************************************************************/733matrix_TYP *pres(bahn **s,734bravais_TYP *G,735int *OPT){736737matrix_TYP *M,738*x,739*y,740*g,741**GENU,742**GENUINV,743**GENINV = NULL;744745static int has_been_called_recursively;746747int i,748ii,749j,750k,751l = 0,752GENU_NO = 0,753**GENUW,754**GW,755speicher = 256 - 8,756*w2 = NULL,757**w;758759if ((!has_been_called_recursively && G->gen_no > G->dim) || s == NULL){760/* many gerators, treat it differently */761/* and prevent using users the form pres_on_many_generators just because they are too lazy to calculate */762/* s, and calculate it for them */763has_been_called_recursively = TRUE;764return pres_on_many_generators(G,OPT);765}766767has_been_called_recursively = FALSE;768769GENU = (matrix_TYP **) malloc(sizeof(matrix_TYP *));770GENUINV = (matrix_TYP **) malloc(sizeof(matrix_TYP *));771GENUW = (int **) malloc(sizeof(int *));772773GENINV = (matrix_TYP **) calloc(G->gen_no,sizeof(matrix_TYP*));774775for (i=0;i<G->gen_no;i++)776GENINV[i] = long_mat_inv(G->gen[i]);777778/* alloc space for the result */779w = (int **) calloc(speicher , sizeof(int*));780781s[0]->gen_no = G->gen_no;782783for (i=G->dim-1;i>=0;i--){784for (j=0;j<s[i]->length;j++){785786/* relations of the first kind */787if (i==0){788ii=G->gen_no;789}790else{791ii = G->gen_no + s[i]->gen_no;792}793for (k=0;k<ii;k++){794795if ( l == speicher){796speicher += 256;797w = (int **) realloc(w,speicher * sizeof(int*));798}799800if (k < G->gen_no){801g = G->gen[k];802}803else{804g = s[i]->generators[k - G->gen_no];805}806807x = mat_mul(g,s[i]->representatives[j]);808809if (!is_element(x,G,s,&w2)){810fprintf(stderr,"error in pres\n");811exit(3);812}813814if (DEBUG){815y = mapped_word(w2,G->gen,GENINV);816817if (mat_comp(x,y)){818fprintf(stderr,"error in pres\n");819exit(3);820}821free_mat(y);822823}824825826if (k<G->gen_no){827w[l] = relator3(k,s[i]->words[j],w2);828}829else{830w[l] = relator2(get_word_to_generator(s[i],g),s[i]->words[j],w2);831}832833normalize_word(w[l]);834con_reduce(w[l]);835836if (DEBUG){837y = mapped_word(w[l],G->gen,GENINV);838Check_mat(y);839if (!y->flags.Diagonal){840fprintf(stderr,"error in pres\n");841exit(3);842}843free_mat(y);844}845846if (w[l][0] == 0){847free(w[l]);848}849else{850/* put_word(w[l],"M"); */851l++;852}853854free_mat(x);855free(w2); w2 = NULL;856857}858859860}861862if (i<G->dim -1 ){863/* relations of the second kind, conjugation */864GENU = (matrix_TYP **) realloc(GENU,(GENU_NO+1+s[i+1]->gen_no)865*sizeof(matrix_TYP *));866GENUW = (int **) realloc(GENUW,(GENU_NO+1+s[i+1]->gen_no)867*sizeof(int*));868869for (k=0;k<s[i+1]->gen_no;k++){870GENU[GENU_NO + k] = s[i+1]->generators[k];871GENUW[GENU_NO + k] = get_word_to_generator(s[i+1],872s[i+1]->generators[k]);873}874GENU_NO += s[i+1]->gen_no;875876GW = (int **) malloc(s[i]->gen_no * sizeof(int*));877if (i==0){878879for (k=0;k<G->gen_no;k++){880GW[k] = (int *) malloc(2*sizeof(int));881GW[k][0] = 1;882GW[k][1] = k+1;883}884885con_relations(G,GENINV,G->gen,GENINV,886GW,s,i,887&w,&l,&speicher,888GENU,GENUW,GENU_NO);889890for (k=0;k<G->gen_no;k++)891free(GW[k]);892}893else{894895GENUINV = (matrix_TYP **) realloc(GENUINV,896s[i]->gen_no*sizeof(matrix_TYP*));897for (k=0;k<s[i]->gen_no;k++){898GW[k] = (int *) get_word_to_generator(s[i],s[i]->generators[k]);899GENUINV[k] = search_inverse(s[i],s[i]->generators[k]);900}901902con_relations(G,GENINV,s[i]->generators,GENUINV,903GW,s,i,904&w,&l,&speicher,905GENU,GENUW,GENU_NO);906}907908free(GW);909910}911912913}914915/* put_presentation(w,l,G,"G4"); */916917simplify_presentation(w,&l);918919if (DEBUG){920for (i=0;i<l;i++){921y = mapped_word(w[0],G->gen,GENINV);922Check_mat(y);923if (!y->flags.Diagonal){924fprintf(stderr,"error in pres\n");925exit(3);926}927free_mat(y);928}929}930931if (GENINV){932for (i=0;i<G->gen_no;i++)933if (GENINV[i]) free_mat(GENINV[i]);934free(GENINV);935}936937938if (OPT && OPT[0])939put_presentation(w,l,G,"GSV4");940941j=0;942for (i=0;i<l;i++) if (j<w[i][0]) j = w[i][0];943M = init_mat(l,j,"i");944for (i=0;i<l;i++){945memcpy(M->array.SZ[i],w[i]+1,w[i][0]*sizeof(int));946free(w[i]);947}948free(w);949free(GENU);950free(GENUINV);951free(GENUW);952953/* put_mat(M,0,0,0); */954955return M;956} /* pres(....) */957958959960961