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<longtools.h>4#include<tools.h>5#include"zass.h"67891011matrix_TYP *scalar(long n,long a)12/* liefert eine skalarmatrix mit dem eintrag a */13{14long i;15matrix_TYP *erg;1617erg = init_mat(n,n,"k");1819for (i=0;i<n;i++){erg->array.SZ[i][i]=a;}2021return erg;22} /* scalar */2324matrix_TYP *matrizen_in_word(matrix_TYP **mat,matrix_TYP **matinv,word g)25/* geht davon aus, das alle (benoetigten) matrizen in **mat26quadratisch von gleicher groesse sind. anderfalls wird nicht abgebrochen */27{28matrix_TYP *erg,*tmp_matrix;29long i,n;3031n = mat[0]->cols;32erg = scalar(n,g.faktor);3334for (i=0;i<=g.last;i++){35if (g.pointer[i]>0){36tmp_matrix = mat_mul(erg,mat[g.pointer[i]-1]);37free_mat(erg);38erg = tmp_matrix;39}40else if (g.pointer[i]<0){41/* 1ster fall, die inverse ist noch nicht berechnet */42if (matinv[-g.pointer[i]-1]==NULL){43matinv[-g.pointer[i]-1]= mat_inv(mat[-g.pointer[i]-1]);44}45tmp_matrix = mat_mul(erg,matinv[-g.pointer[i]-1]);46free_mat(erg);47erg = tmp_matrix;48}49}5051if (INFO_LEVEL & 4){52put_mat(erg,NULL,NULL,2);53}5455return erg;56} /* matrizen_in_word */57585960static void norm_word(word *g)61/* soll die auftretenden worte vereinfachen */62{63int i,j;6465/* wenn der faktor des relators = 0, dann auch der relator */66if (g[0].faktor==0){67g[0].last = -1;68for (i=0;i<g[0].speicher;i++){69g[0].pointer[i]=0;70}71}7273/* suchen nach einsen (representiert durch nullen) im relator */74i = 0;75while(i<=g[0].last){76if (g[0].pointer[i]==0){77for (j=i+1;j<=g[0].last;j++){78g[0].pointer[j-1]=g[0].pointer[j];79}80g[0].last--;81}82else{83i++;84}85}8687/* suchen nach ausdruecken wie x_j * x_j^(-1) */88i=0;89while(i<g[0].last){90if (g[0].pointer[i]==(-g[0].pointer[i+1])){91g[0].pointer[i]=0;92g[0].pointer[i+1]=0;93/* und jetzt die enstandenen nullen eliminieren94(geht nicht durch vertauschen der while-schleifen, weil95so x_1 * x_2 * x_2^(-1) * x_1^(-1) nicht erkannt wuerde) */96norm_word(g);97/* nur der sicherheit halber */98i= -1;99}100i++;101}102103return;104}105106extern int wordfree(word *a)107{108109free(a[0].pointer);110111return TRUE;112}113114static int ini_word(word *a,int laenge)115{116a[0].pointer = (long *) malloc(laenge * sizeof(long));117a[0].speicher = laenge;118a[0].last = 0;119120return TRUE;121}122123124static int test_relator(matrix_TYP **mat,matrix_TYP **matinv,word *relator,long anz)125/* testet, ob die relationen in *relator erfuellt sind:126wenn ja: return true; sonst false */127{128long i,n;129int flag;130matrix_TYP *id,*tmp;131132flag = TRUE;133i = 0;134n = mat[0]->cols;135id = scalar(n,1);136137while(i<anz && flag==TRUE){138tmp = matrizen_in_word(mat,matinv,relator[i]);139140if (INFO_LEVEL & 4){141put_mat(tmp,NULL,"tmp in test_relator",2);142put_mat(id,NULL,"id in test_relator",2);143}144145if (cmp_mat(tmp,id)!=0){146flag = FALSE;147}148i++;149free_mat(tmp);150}151152free_mat(id);153return flag;154} /* test_relator */155156void matrix_2_word(matrix_TYP *matrix,word *relator,long zeile)157{158long i,hilf;159160if (relator[0].speicher !=0 ){161free(relator[0].pointer);162relator[0].speicher = 0;163}164165ini_word(relator,matrix->cols);166167relator[0].last = matrix->cols -1;168relator[0].faktor = 1;169170hilf = 0;171for (i=0;i<=relator[0].last;i++){172relator[0].pointer[i] = matrix->array.SZ[zeile][i+hilf];173if (relator[0].pointer[i] == 0){i--;hilf++;relator[0].last--;}174}175176norm_word(relator);177178return;179} /* matrix_2_word */180181static matrix_TYP *fox_deriv_mat(matrix_TYP **mat, matrix_TYP **matinv,word a,long j)182/* soll rekursiv die j-te fox-derivation vom word a berechnen und sie183in erg abspeichern */184{185word g,h;186long i,teil;187matrix_TYP *erg,188*nu_g,189*nu_h,190*g_mat,191*tmp;192193if (INFO_LEVEL & 4){194printf("fox_deriv_mat\n");195}196197norm_word(&a);198199if ( a.last==0 || a.last == (-1) ){200if (a.pointer[0]==j){201erg = scalar(mat[0]->cols,1);202}203else if (a.pointer[0]==(-j)){204tmp = scalar(mat[0]->cols,-1);205if (matinv[j-1]==NULL){206matinv[j-1]=mat_inv(mat[j-1]);207}208erg = mat_mul(tmp,matinv[j-1]);209free_mat(tmp);210}211else{212erg = scalar(mat[0]->cols,0);213}214}215else{216217/* die ersten teil erzeuger von a werden in g218gespeichert, der rest in h */219teil = 1;220ini_word(&g,teil);221ini_word(&h,a.last);222223for (i=0;i<=a.last;i++){224if (i<teil){225g.pointer[i] = a.pointer[i];226}227else{228h.pointer[i-teil] = a.pointer[i];229}230}231232g.last= teil-1;233h.last= a.last-teil;234g.faktor=1;235h.faktor=1;236nu_g = fox_deriv_mat(mat,matinv,g,j);237nu_h = fox_deriv_mat(mat,matinv,h,j);238239g_mat = matrizen_in_word(mat,matinv,g);240241tmp = mat_mul(g_mat,nu_h);242243erg = mat_add(nu_g,tmp,One,One);244245wordfree(&g);246wordfree(&h);247248free_mat(g_mat);249free_mat(nu_g);250free_mat(nu_h);251free_mat(tmp);252253}254255if (INFO_LEVEL &4){256printf("return aus fox_deriv_mat\n");257}258259return erg;260}261262263matrix_TYP *calc_B(matrix_TYP **mat,long anz_erzeuger)264{265long i,k,l,n;266matrix_TYP *B;267268n = mat[0]->cols;269270/* reservieren des speichers fuer die matrix B, die die271erzeuger - id uebereinander enthaelt */272B = init_mat(n*anz_erzeuger,n,"k");273274/* belegen der matrix B */275for (i=0;i<anz_erzeuger;i++){276for (k=0;k<n;k++){277for (l=0;l<n;l++){278if (k == l){279B->array.SZ[k+i*n][l]=mat[i]->array.SZ[k][l]-1;280}281else{282B->array.SZ[k+i*n][l]=mat[i]->array.SZ[k][l];283}284}285}286}287288if (INFO_LEVEL & 4){289put_mat(B,NULL,"%B",2);290}291292return B;293} /* calc_B */294295static matrix_TYP *calc_A(matrix_TYP **mat,matrix_TYP **matinv,word *relator,296int erzeuger,int relatoren)297{298matrix_TYP *eingesetzt,299*A;300long i,j,k,l,n;301302/* reservieren von speicher fuer die grosse matrix A */303n = mat[0]->cols;304A = init_mat(n*relatoren,n*erzeuger,"k");305306/* berechnen der j-ten foxableitung des i-ten relators */307for (i=0;i<relatoren;i++){308for (j=1;j<=erzeuger;j++){309310eingesetzt = fox_deriv_mat(mat,matinv,relator[i],j);311312if (INFO_LEVEL & 4){313put_mat(eingesetzt,NULL,NULL,2);314}315316Check_mat(eingesetzt);317318/* umspeichern der eintraege aus der fox-ableitung in das319gleichungssystem A */320for (k=0;k<n;k++){321for (l=0;l<n;l++){322A->array.SZ[n*i+k][n*(j-1)+l] = eingesetzt->array.SZ[k][l];323}324}325326/* die matrix eingesetzt wird wieder benutzt */327free_mat(eingesetzt);328}329}330331if (is_option('s')){332put_mat(A,FILENAMES[2],"system of congruences to determine H^1(G,**)",2);333}334335if (INFO_LEVEL & 4){336put_mat(A,NULL,NULL,2);337}338339return A;340} /* calc_A */341342343344matrix_TYP** cohomology(long *dim,345matrix_TYP **mat,346matrix_TYP **matinv,347word *relator,348int erzeuger,349int relatoren)350{ matrix_TYP *A,351*B,352*B_tr,353*cozykel,354*elementar,355**tmp;356357int corang_a,rang_b,erg,i;358359if (INFO_LEVEL &4){360printf("in cohomology\n");361}362363/* ueberprueft die gegeben relatoren */364if (test_relator(mat,matinv,relator,relatoren)==FALSE){365fprintf(stderr,"Error in Cohomlogy:\n");366fprintf(stderr,"One of the given relators it not satisfied\n");367fprintf(stderr,"by this generating set.\n");368fflush(stderr);369exit(3);370}371372/* berechnet die matrix des fuer die cozykel zu373loesenden gleichungssystems */374A = calc_A(mat,matinv,relator,erzeuger,relatoren);375376if (INFO_LEVEL & 4){377put_mat(A,NULL,"A",2);378}379380/* enthaelt nur die erzeuger - id hintereinander,381spannt also den raum der coraender auf */382B = calc_B(mat, erzeuger);383B_tr = tr_pose(B);384385386/* shrink the linear system of equations by a gauss algorithm,387note that this also removes the dependence of the result388from the given presentation */389long_row_hnf(A);390391/* loesen der gleichungssysteme */392tmp = cong_solve(A);393394cozykel = tmp[0];395elementar = tmp[1];396397if (INFO_LEVEL &4){398put_mat(cozykel,NULL,"cozykel",2);399put_mat(elementar,NULL,"elementar",2);400}401402rang_b = tgauss(B_tr);403404/* berechnen des coranges von A */405corang_a = 0;406for (i=0;i<elementar->cols;i++){407if (elementar->array.SZ[i][i]==0){408corang_a++;409}410}411412dim[0] = erg = corang_a - rang_b;413414if (INFO_LEVEL & 4){415printf("corang_a %d\n",corang_a);416printf("rang_b %d\n",rang_b);417printf("erg %d\n",erg);418}419420if (erg == 0){421/* die Q-dimesionen der Coraender und Cozykel sind gleich, d.h.422es kommt nur torsion dazu */423for (i=elementar->cols-1;0<=i;i--){424if (elementar->array.SZ[i][i]==0){425kill_col(elementar,i);426kill_row(elementar,i);427kill_col(cozykel,i);428}429}430}431else{432/* es interesiert */433for (i=elementar->cols-1;0<=i;i--){434if (elementar->array.SZ[i][i]!=0){435kill_col(elementar,i);436kill_row(elementar,i);437kill_col(cozykel,i);438}439}440}441442if (INFO_LEVEL & 4){443put_mat(A,NULL,NULL,2);444put_mat(B,NULL,NULL,2);445put_mat(elementar,NULL,NULL,2);446put_mat(cozykel,NULL,NULL,2);447}448449free_mat(A);450free_mat(B);451free_mat(B_tr);452free_mat(elementar);453454/* free_mat(cozykel); */455/* free_mat(tmp2); */456tmp[0] = cozykel;457tmp[1] = tmp[3];458459tmp = (matrix_TYP **) realloc(tmp,3 *sizeof(matrix_TYP *));460/* tmp[1] = elementar; */461462return tmp;463} /* cohomology */464465466467