GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#include "typedef.h"1#include "contrib.h"2#include "matrix.h"3#include "getput.h"4#include "idem.h"5#include "sort.h"6#include "orbit.h"7#include "bravais.h"89static int *trace_list_B;10static int *order_list_B;1112static int *traces_of_inv_A;13static int **traces_of_prod_A;1415static int *image_of_Gen_A;1617static void *xmalloc (int size, const char *string)18{19void *pointer;2021if( (pointer = malloc(size)) == NULL)22{23perror (string);24exit (2);25}2627return pointer;28}2930static int krit_kon_mat (matrix_TYP **A, matrix_TYP **B, int anz,31matrix_TYP ***M, int *dim)32{33matrix_TYP **AA, **BA, **AB,**Prod, *mat;34int ab, aa, ba, pp,i,j;3536AB = solve_endo (A, B, anz, &ab);37BA = solve_endo (B, A, anz, &ba);38*dim = ab;39*M = AB;40if (ab == ba)41{42AA = solve_endo (A, A, anz, &aa);43if (ab == aa)44{45Prod = (matrix_TYP **) xmalloc (aa * aa * sizeof (matrix_TYP *), "krit_kon_mat"); /* Prod = (matrix_TYP **) calloc (aa*aa, sizeof (matrix_TYP *)); */46for (i=0; i<aa; i++)47for (j=0; j<aa; j++)48Prod[i*aa + j] = mat_mul (AB[i], BA[j]);4950mat = mat_to_line (Prod, aa*aa);5152for (i=0; i<aa*aa; i++)53free_mat (Prod[i]);54free (Prod);5556pp = tgauss (mat);57free_mat (mat);5859if (pp == aa)60{61if (ab != 0)62{63for (i=0; i<ba; i++)64free_mat (BA[i]);65free (BA);66}67if (aa != 0)68{69for (i=0; i<aa; i++)70free_mat (AA[i]);71free (AA);72}73return 1;74}75else76{77if (ab != 0)78{79for (i=0; i<ba; i++)80free_mat (BA[i]);81free (BA);82}83if (aa != 0)84{85for(i=0; i<aa; i++)86free_mat (AA[i]);87free (AA);88}89return 0;90}91}92else93{94if (ab != 0)95{96for (i=0; i<ba; i++)97free_mat (BA[i]);98free (BA);99}100if (aa != 0)101{102for (i=0; i<aa; i++)103free_mat (AA[i]);104free (AA);105}106return 0;107}108}109else110{111if (ab != 0)112{113for (i=0; i<ba; i++)114free_mat (BA[i]);115free (BA);116}117if (aa != 0)118{119for (i=0; i<aa; i++)120free_mat (AA[i]);121free (AA);122}123return 0;124}125126}127128129static matrix_TYP *suche_max_rank (matrix_TYP *mat_best, matrix_TYP **solve,130int dim, int step, int *found,131int rank_mat_best, int *rank)132{133matrix_TYP **alternative, *m, *n, *B, *gau, *mat;134int i, l, rank_m, rank_n, rank_B, rank_mat, z = 0;135136B = solve[step];137gau = ggauss(B);138rank_B = gau->rows;139alternative = (matrix_TYP **) calloc (rank_B,sizeof(matrix_TYP *));140free_mat (gau);141142for(l=1; l<rank_B+1 && rank_mat_best != B->rows; l++)143{144mat = imat_add (mat_best,B,1,l);145gau = ggauss (mat);146rank_mat = gau->rows;147free_mat (gau);148if (rank_mat > rank_mat_best)149{150rank_mat_best=rank_mat;151for (i=0; i<z; i++)152free_mat(alternative[i]);153z = 0;154if(mat_best != solve[0])155free_mat(mat_best);156mat_best=mat;157}158else159{160if(rank_mat == rank_mat_best)161{162alternative[z] = mat;163z++;164}165else166free_mat(mat);167}168}169*rank = rank_mat_best;170if (rank_mat_best == B->rows)171{172*found = 1;173for(i=0; i<z; i++)174free_mat (alternative[i]);175free (alternative);176177if (mat_best != solve[0])178return mat_best;179else180return copy_mat(mat_best);181}182if(step == dim-1)183{184*found = 0;185for (i=0; i<z; i++)186free_mat (alternative[i]);187free (alternative);188return mat_best;189}190m = suche_max_rank (mat_best, solve, dim, step+1, found,191rank_mat_best, &rank_m);192while (z > 0 && *found == 0)193{194n = suche_max_rank (alternative[z-1], solve, dim, step+1, found,195rank_mat_best, &rank_n);196z--;197if(rank_n > rank_m)198{199free_mat (m);200m = n;201rank_m = rank_n;202}203else204free_mat (n);205}206*rank = rank_m;207208for (i=0; i<z; i++)209free_mat (alternative[i]);210free (alternative);211212return m;213}214215216static matrix_TYP *suche_kon_mat (matrix_TYP **solve, int dim)217{218int rank_mat_best, found = 0;219matrix_TYP *A, *gau, *mat_best;220221A = solve[0];222gau = ggauss (A);223/* rank_mat_best=gau->rows; */224if(dim > 1)225mat_best = suche_max_rank (A, solve, dim, 1, &found, gau->rows,226&rank_mat_best);227else228{229rank_mat_best = gau->rows;230mat_best = copy_mat (A);231}232free_mat (gau);233if(rank_mat_best != A->rows)234printf("Keine invertierbare Loesung gefunden.\n");235return(mat_best);236}237238/* Hier wird die Ordnung von m ausgerechnet, und zurueckgegeben. */239240static int order (matrix_TYP *m)241{242int i = 1;243matrix_TYP *n, *E;244245n = copy_mat (m);246E = einheitsmatrix(m->rows);247248while(cmp_mat(n, E) != 0)249{250n = mat_muleq(n, m);251252i++;253}254255free_mat(E);256257free_mat(n);258259return i;260}261262static int **calc_traces_of_prod (bravais_TYP *G)263{264int **mat, i, j;265266matrix_TYP *waste;267268mat = (int **) xmalloc(G->gen_no*sizeof(int *), "calc_traces_of_prod");269270for (i=0; i<G->gen_no; i++)271mat[i] = (int *) xmalloc(G->gen_no*sizeof(int),"calc_traces_of_prod");272273/* Keine Lust Symmetrie der Matrix zu benutzen! */274for (i=0; i<G->gen_no; i++)275for (j=0; j<G->gen_no; j++)276{277waste = mat_mul(G->gen[i],G->gen[j]);278279mat[i][j] = trace(waste);280281free_mat(waste);282}283284285return mat;286}287288static int *calc_traces_of_inv (bravais_TYP *G)289{290int *mat, i;291292matrix_TYP *waste;293294mat = (int *) xmalloc(G->gen_no*sizeof(int), "calc_traces_of_inv");295296297for (i=0; i<G->gen_no; i++)298{299waste = mat_inv(G->gen[i]);300301mat[i] = trace(waste);302303free_mat(waste);304}305306307return mat;308}309310/* Get Conjugation Classes of "G" under Group "H". Store the con_class311of each element in "list[]" and an "representant_of_con_class" in312the array. Return_value is the last array. */313314static int *con_classes (matrix_TYP **G, int order_of_G,315bravais_TYP *H, int *number_of_con_classes)316{317matrix_TYP **orbit;318int i, j, pos_in_list, length, *representant_of_con_class, *list;319int orbit_options[6] = {4, 0, 0, 0, 0, 0};320/* acting.from = Left,321acting.by = Conjugation;*/322323*number_of_con_classes = 0;324325list = (int *)xmalloc(order_of_G * sizeof(int), "con_classes");326327representant_of_con_class = (int *)xmalloc(order_of_G * sizeof(int),328"con_classes");329/* Worst-Case-Allocation: Every element its own con_class. */330331for (i=0; i<order_of_G; i++)332list[i] = -1;333334for (i=0; i<order_of_G; i++)335if(list[i] == -1)336{337orbit = orbit_alg(G[i], H, NULL, orbit_options,338&length);339340representant_of_con_class[*number_of_con_classes] = i;341342for (j=0; j<length; j++)343{344pos_in_list = mat_search (orbit[j], G, order_of_G, mat_comp);345list[pos_in_list] = *number_of_con_classes;346347free_mat (orbit[j]);348}349350free (orbit);351352(*number_of_con_classes) ++;353354}355356representant_of_con_class = (int *) realloc(representant_of_con_class, *number_of_con_classes * sizeof(int));357/* Just for the fun of saving a bit of memory. */358359free(list);360361return representant_of_con_class;362}363364365366/* compute the trace of every element in "group" and store it in "trace_list". */367368static int *compute_trace (matrix_TYP **group, int group_order)369{370int i;371372int *trace_list = (int *) xmalloc (group_order * sizeof(int), "compute_trace");373374for (i=0; i<group_order; i++)375trace_list[i] = trace (group[i]);376377return trace_list;378379}380381382383/* compute the order of every element in "group" and store it in "order_list". */384385static int *compute_order (matrix_TYP **group, int group_order)386{387int i;388389int *order_list = (int *) xmalloc (group_order * sizeof(int), "compute_order");390391for (i=0; i<group_order; i++)392order_list[i] = order (group[i]);393394return order_list;395396}397398399static int end_test (matrix_TYP **matrix, matrix_TYP **A, matrix_TYP **B,400int number_of_el_in_A)401{402matrix_TYP **AA;/*, *mat;*/403int found, dim, i;404405found = krit_kon_mat(A, B, number_of_el_in_A, &AA, &dim);406407if (found == TRUE)408{409/*mat = suche_kon_mat(AA,dim);410*matrix = mat;*/411*matrix = suche_kon_mat(AA, dim);412413for(i=0; i<dim; i++)414free_mat (AA[i]);415free (AA);416}417418return found;419}420421/* returns centralizer of the group generated by elements "H" in422"list_of_H". "list_of_H" is "number_of_H"-elements long. */423424static bravais_TYP *get_centralizer(matrix_TYP **H, bravais_TYP *G,425int list_of_H[], int number_of_H)426{427bravais_TYP *C1, *C2;428429matrix_TYP **waste;430431int orbit_options[6] = {4, 0, 3, 0, 0, 0};432/*acting.and_calc_stab = TRUE;*/433/* act.from = Left,434act.by = Conjugation;*/435int i, j, laenge;436437C1 = copy_bravais (G);438439C2 = init_bravais (G->dim);440441/* Dies laeuft in etwa darauf hinaus die Stabilisatoren aller "H"s zu442schneiden. */443for (i=0; i<number_of_H; i++)444{445waste = orbit_alg(H[list_of_H[i]], C1, C2, orbit_options, &laenge);446447for(j=0; j<laenge; j++)448free_mat(waste[j]);449free(waste);450451free_bravais(C1);452453C1 = C2;454455C2 = init_bravais (G->dim);456457}458459free_bravais (C2);460461return C1;462}463464465static int traces_are_ok(matrix_TYP *new_element, bravais_TYP *Group_A, matrix_TYP **Group_B, int next_gen)466{467matrix_TYP *waste;468469int i;470471waste = mat_inv(new_element);472473if (trace(waste) != traces_of_inv_A[next_gen])474{475free_mat (waste);476477return FALSE;478}479480free_mat (waste);481482waste = mat_mul(new_element, new_element);483484if (trace(waste) != traces_of_prod_A[next_gen][next_gen])485{486free_mat (waste);487return FALSE;488}489490free_mat (waste);491492for (i=0; i<next_gen; i++)493{494waste = mat_mul(new_element, Group_B[image_of_Gen_A[i]]);495496if (trace(waste) != traces_of_prod_A[next_gen][i])497{498free_mat (waste);499return FALSE;500}501502free_mat (waste);503}504505506return TRUE;507508}509510511/* function tests if mapping of the generators "Gen_A" in "Group_B" exists512which projects "Gen_A[0],..,Gen_A[next_gen -1]" on513"Group_B[image_of_Gen_A[0]],...,Group_B[image_of_Gen_A]". writes a514possible result back into the rest of the global array "image_of_Gen_A[]".515Returns "1" if it succeeds and "0" if it does not. */516static int construct_Image_Gen_A (int next_gen, bravais_TYP *Gen_A,517int group_order, bravais_TYP *Gen_B,518matrix_TYP **Group_B)519{520int *rep_con_class, number_of_con_classes,521trace_next_gen, order_next_gen;522523matrix_TYP *matrix, **Bild;524525int i, j;526527bravais_TYP *centralizer;528529trace_next_gen = trace(Gen_A->gen[next_gen]);530order_next_gen = order(Gen_A->gen[next_gen]);531532/* Stabilizer of trivial group is whole group. Maybe faster. */533if (next_gen> 0)534centralizer = get_centralizer(Group_B, Gen_B, image_of_Gen_A, next_gen);535else536centralizer = copy_bravais(Gen_B);537538rep_con_class = con_classes (Group_B, group_order, centralizer,539&number_of_con_classes);540541542543Bild = (matrix_TYP **)xmalloc( (next_gen+1) * sizeof(matrix_TYP *),"construct_Image_Gen_A");544545546for (i=0; i<next_gen; i++)547Bild[i] = Group_B[image_of_Gen_A[i]];548549550for (i=0; i<number_of_con_classes; i++)551if(trace_list_B[rep_con_class[i]] == trace_next_gen &&552order_list_B[rep_con_class[i]] == order_next_gen &&553traces_are_ok(Group_B[rep_con_class[i]], Gen_A, Group_B, next_gen) == TRUE)554{555Bild[next_gen] = Group_B[rep_con_class[i]];556557if(end_test (&matrix, Bild, Gen_A->gen, next_gen + 1) == TRUE)558{559free_mat(matrix);560561image_of_Gen_A[next_gen] = rep_con_class[i];562563if(next_gen + 1 == Gen_A->gen_no)564{565free (Bild);566free (rep_con_class);567568free_bravais (centralizer);569570return TRUE;571}572else573if (construct_Image_Gen_A (next_gen + 1, Gen_A, group_order, Gen_B, Group_B) == TRUE)574{575free (Bild);576free (rep_con_class);577578free_bravais (centralizer);579580return TRUE;581}582583}584585}586587free (Bild);588free (rep_con_class);589590free_bravais (centralizer);591592return FALSE;593}594595596matrix_TYP *suche_kand (bravais_TYP *Gen_A, bravais_TYP *Gen_B)597{598matrix_TYP **Group_A, **Group_B;599int group_order,laenge, i;600601matrix_TYP *matrix = NULL, **Bild;602603int orbit_options[6] = {0, 0, 0, 0, 0, 0};604605/* acting.from = Left,606acting.by = Normal_Operation,607acting.on = Matrix_M,608acting.until_orbit_length = 0,609acting.and_calc_stab = FALSE,610acting.until_stab_length = 0;611acting.with_inverse = FALSE;612*/613614615/* Check, if the groups have same dimension. */616if (Gen_A->dim != Gen_B->dim)617{618fprintf (stdout, "Groups have different dimension.\n");619620return NULL;621}622623/* Compute all elements of the two groups */624Group_A = orbit_alg (Gen_A->gen[0], Gen_A, NULL, orbit_options, &group_order);625626Group_B = orbit_alg (Gen_B->gen[0], Gen_B, NULL, orbit_options, &laenge);627628/* We were only interested in the order of Group A,629now the Generators are enough. */630for (i=0; i<group_order; i++)631free_mat (Group_A[i]);632free(Group_A);633634/* Check, if the groups have same order. */635if (group_order != laenge)636{637fprintf (stdout, "Groups are of different order.\n");638639for (i=0; i<laenge; i++)640free_mat (Group_B[i]);641642free (Group_B);643644return NULL;645}646647/* This is necessary because of a "search_mat", at least this is648what I believe. */649mat_quicksort (Group_B, 0, group_order - 1, mat_comp);650651652653/* orbit_options[0] = 4;*/654/* acting.from = Left,655acting.by = Conjugation;*/656657658659trace_list_B = compute_trace (Group_B, group_order);660661order_list_B = compute_order (Group_B, group_order);662663664traces_of_prod_A = calc_traces_of_prod (Gen_A);665traces_of_inv_A = calc_traces_of_inv (Gen_A);666667668image_of_Gen_A = (int *) xmalloc (Gen_A->gen_no * sizeof(int), "suche_kand");669670671if (construct_Image_Gen_A( 0, Gen_A,group_order, Gen_B, Group_B) == TRUE)672{673Bild = (matrix_TYP **)xmalloc(Gen_A->gen_no * sizeof(matrix_TYP *),"construct_Image_Gen_A");674675for (i=0; i<Gen_A->gen_no; i++)676Bild[i] = Group_B[image_of_Gen_A[i]];677678679if(end_test (&matrix, Bild, Gen_A->gen, Gen_A->gen_no) != TRUE)680matrix = NULL;681682free(Bild);683}684685686free (image_of_Gen_A);687688for (i=0; i<group_order; i++)689free_mat (Group_B[i]);690free (Group_B);691692free(trace_list_B);693694free(order_list_B);695696697for (i=0; i<Gen_A->gen_no; i++)698free (traces_of_prod_A[i]);699free (traces_of_prod_A);700701free (traces_of_inv_A);702703704return matrix;705}706707708709710711712