1 /****************************************************************************
2 **
3 *A  interactive_pga.c           ANUPQ source                   Eamonn O'Brien
4 **
5 *Y  Copyright 1995-2001,  Lehrstuhl D fuer Mathematik,  RWTH Aachen,  Germany
6 *Y  Copyright 1995-2001,  School of Mathematical Sciences, ANU,     Australia
7 **
8 */
9 
10 #include "pq_defs.h"
11 #include "pcp_vars.h"
12 #include "pga_vars.h"
13 #include "constants.h"
14 #include "menus.h"
15 #include "standard.h"
16 #include "pq_functions.h"
17 #include "global.h"
18 
19 #define MAX_INTERACTIVE_OPTION 18 /* maximum number of menu options */
20 
21 #define COMBINATION 100
22 
23 /* interactive menu for p-group generation */
24 
interactive_pga(Logical group_present,FILE * StartFile,int group_nmr,int *** auts,struct pga_vars * pga,struct pcp_vars * pcp)25 void interactive_pga(Logical group_present,
26                      FILE *StartFile,
27                      int group_nmr,
28                      int ***auts,
29                      struct pga_vars *pga,
30                      struct pcp_vars *pcp)
31 {
32    struct pga_vars flag;
33    int option;
34    Logical soluble_group = TRUE;
35 
36    FILE *OutputFile = 0;
37    FILE *LINK_input = 0;
38 
39    char *StartName = 0;
40    int t;
41 
42    int **perms = 0;
43    int index;
44    int **S = 0;
45    int k;
46    int K;
47    int label;
48    int *a = 0, *b = 0;
49    char *c = 0;
50    int *orbit_length = 0;
51    int nmr_of_exponents;
52    int *subset = 0;
53    int alpha;
54    int upper_step;
55    int rep;
56    int i;
57 
58    list_interactive_pga_menu();
59 
60    do {
61       option = read_option(MAX_INTERACTIVE_OPTION);
62       switch (option) {
63 
64       case -1:
65          list_interactive_pga_menu();
66          break;
67 
68       case SUPPLY_AUTS:
69          auts = read_auts(PGA, &pga->m, &nmr_of_exponents, pcp);
70 #ifdef HAVE_GMP
71          autgp_order(pga, pcp);
72 #endif
73          pga->soluble = TRUE;
74          start_group(&StartFile, auts, pga, pcp);
75          break;
76 
77       case EXTEND_AUTS:
78          extend_automorphisms(auts, pga->m, pcp);
79          print_auts(pga->m, pcp->lastg, auts, pcp);
80          break;
81 
82       case RESTORE_GP:
83          StartName = GetString("Enter input file name: ");
84          StartFile = OpenFileInput(StartName);
85          if (StartFile != NULL) {
86             read_value(TRUE, "Which group? ", &group_nmr, 0);
87             auts = restore_group(TRUE, StartFile, group_nmr, pga, pcp);
88             RESET(StartFile);
89          }
90          break;
91 
92       case DISPLAY_GP:
93          print_presentation(FALSE, pcp);
94          print_structure(1, pcp->lastg, pcp);
95          print_pcp_relations(pcp);
96          break;
97 
98       case SINGLE_STAGE:
99          t = runTime();
100          if (group_present && pga->m == 0)
101             start_group(&StartFile, auts, pga, pcp);
102          assert(OutputFile);
103          construct(1,
104                    &flag,
105                    SINGLE_STAGE,
106                    OutputFile,
107                    StartFile,
108                    0,
109                    ALL,
110                    group_nmr,
111                    pga,
112                    pcp);
113          t = runTime() - t;
114          printf("Time for intermediate stage is %.2f seconds\n", t * CLK_SCALE);
115          break;
116 
117       case DEGREE:
118          read_step_size(pga, pcp);
119          read_subgroup_rank(&k);
120          query_exponent_law(pga);
121          enforce_laws(pga, pga, pcp);
122          extend_automorphisms(auts, pga->m, pcp);
123          step_range(k, &pga->s, &upper_step, auts, pga, pcp);
124 
125          if (pga->s > upper_step)
126             printf("Desired step size is invalid for current group\n");
127          else {
128             if (pga->s < upper_step) {
129                printf("The permitted relative step sizes range from %d to %d\n",
130                       pga->s,
131                       upper_step);
132                read_value(
133                    TRUE, "Input the chosen relative step size: ", &pga->s, 0);
134             }
135 
136 
137             store_definition_sets(pga->r, pga->s, pga->s, pga);
138             get_definition_sets(pga);
139             pga->print_degree = TRUE;
140             compute_degree(pga);
141             pga->print_degree = FALSE;
142          }
143          break;
144 
145       case PERMUTATIONS:
146          if (pga->Degree != 0) {
147             t = runTime();
148 
149             query_solubility(pga);
150             pga->trace = FALSE;
151             if (pga->soluble)
152                query_space_efficiency(pga);
153             else
154                pga->space_efficient = FALSE;
155             query_perm_information(pga);
156 
157             strip_identities(auts, pga, pcp);
158             soluble_group =
159                 (pga->soluble || pga->Degree == 1 || pga->nmr_of_perms == 0);
160             if (!soluble_group) {
161 #if defined(GAP_LINK)
162                StartGapFile(pga);
163 #else
164 #if defined(GAP_LINK_VIA_FILE)
165                start_GAP_file(&LINK_input, auts, pga, pcp);
166 #endif
167 #endif
168             }
169             perms = permute_subgroups(LINK_input, &a, &b, &c, auts, pga, pcp);
170 
171 #if defined(GAP_LINK_VIA_FILE)
172             if (!soluble_group)
173                CloseFile(LINK_input);
174 #endif
175             t = runTime() - t;
176             printf("Time to compute permutations is %.2f seconds\n",
177                    t * CLK_SCALE);
178          } else
179             printf("You must first select option %d\n", DEGREE);
180 
181          break;
182 
183       case ORBITS:
184          orbit_option(option, perms, &a, &b, &c, &orbit_length, pga);
185          break;
186 
187       case STABILISERS:
188       case STABILISER:
189          assert(perms);
190          stabiliser_option(
191              option, auts, perms, a, b, c, orbit_length, pga, pcp);
192          /*
193            free_space (pga->soluble, perms, orbit_length,
194            a, b, c, pga);
195            */
196          break;
197 
198       case MATRIX_TO_LABEL:
199          S = allocate_matrix(pga->s, pga->q, 0, FALSE);
200          subset = allocate_vector(pga->s, 0, FALSE);
201          printf("Input the %d x %d subgroup matrix:\n", pga->s, pga->q);
202          read_matrix(S, pga->s, pga->q);
203          K = echelonise_matrix(S, pga->s, pga->q, pga->p, subset, pga);
204          printf("The standard matrix is:\n");
205          print_matrix(S, pga->s, pga->q);
206          printf("The label is %d\n", subgroup_to_label(S, K, subset, pga));
207          free_vector(subset, 0);
208          break;
209 
210       case LABEL_TO_MATRIX:
211          read_value(TRUE, "Input allowable subgroup label: ", &label, 1);
212          S = label_to_subgroup(&index, &subset, label, pga);
213          printf("The corresponding standard matrix is\n");
214          print_matrix(S, pga->s, pga->q);
215          break;
216 
217       case IMAGE:
218          t = runTime();
219          /*
220            invert_automorphisms (auts, pga, pcp);
221            print_auts (pga->m, pcp->lastg, auts, pcp);
222            */
223          printf("Input the subgroup label and automorphism number: ");
224          read_value(TRUE, "", &label, 1);
225          read_value(FALSE, "", &alpha, 1);
226          printf("Image is %d\n", find_image(label, auts[alpha], pga, pcp));
227          t = runTime() - t;
228          printf("Computation time in seconds is %.2f\n", t * CLK_SCALE);
229          break;
230 
231       case SUBGROUP_RANK:
232          read_subgroup_rank(&k);
233          printf("Closure of initial segment subgroup has rank %d\n",
234                 close_subgroup(k, auts, pga, pcp));
235          break;
236 
237       case ORBIT_REP:
238          printf("Input label for subgroup: ");
239          read_value(TRUE, "", &label, 1);
240          rep = abs(a[label]);
241          for (i = 1; i <= pga->nmr_orbits && pga->rep[i] != rep; ++i)
242             ;
243          printf("Subgroup with label %d has representative %d and is in orbit "
244                 "%d\n",
245                 label,
246                 rep,
247                 i);
248          break;
249 
250 
251       case COMPACT_DESCRIPTION:
252          Compact_Description = TRUE;
253          read_value(TRUE,
254                     "Lower bound for order (0 for all groups generated)? ",
255                     &Compact_Order,
256                     0);
257          break;
258 
259       case AUT_CLASSES:
260          t = runTime();
261          permute_elements();
262          t = runTime() - t;
263          printf("Time to compute orbits is %.2f seconds\n", t * CLK_SCALE);
264          break;
265 
266       /*
267         printf ("Input label: ");
268         scanf ("%d", &l);
269         process_complete_orbit (a, l, pga, pcp);
270         break;
271 
272         case TEMP:
273         printf ("Input label: ");
274         scanf ("%d", &l);
275         printf ("Input label: ");
276         scanf ("%d", &u);
277         for (i = l; i <= u; ++i) {
278         x = IsValidAllowableSubgroup (i, pga);
279         printf ("%d is %d\n", i, x);
280         }
281         StartName = GetString ("Enter output file name: ");
282         OutputFile = OpenFileOutput (StartName);
283         part_setup_reps (pga->rep, pga->nmr_orbits, orbit_length, perms, a, b,
284         c,
285         auts, OutputFile, OutputFile, pga, pcp);
286 
287         list_word (pga, pcp);
288 
289         read_value (TRUE, "Input the rank of the subgroup: ", &pga->q, 1);
290         strip_identities (auts, pga, pcp);
291         break;
292         */
293 
294       case EXIT:
295       case MAX_INTERACTIVE_OPTION:
296          printf("Exiting from interactive p-group generation menu\n");
297          break;
298 
299       } /* switch */
300 
301    } while (option != 0 && option != MAX_INTERACTIVE_OPTION);
302 
303 #if defined(GAP_LINK)
304    if (!soluble_group)
305       QuitGap();
306 #endif
307 }
308 
309 /* list available menu options */
310 
list_interactive_pga_menu(void)311 void list_interactive_pga_menu(void)
312 {
313    printf("\nAdvanced Menu for p-Group Generation\n");
314    printf("-------------------------------------\n");
315    printf("%d. Read automorphism information for starting group\n",
316           SUPPLY_AUTS);
317    printf("%d. Extend and display automorphisms\n", EXTEND_AUTS);
318    printf("%d. Specify input file and group number\n", RESTORE_GP);
319    printf("%d. List group presentation\n", DISPLAY_GP);
320    printf("%d. Carry out intermediate stage calculation\n", SINGLE_STAGE);
321    printf("%d. Compute definition sets & find degree\n", DEGREE);
322    printf("%d. Construct permutations of subgroups under automorphisms\n",
323           PERMUTATIONS);
324    printf("%d. Compute and list orbit information\n", ORBITS);
325    printf("%d. Process all orbit representatives\n", STABILISERS);
326    printf("%d. Process individual orbit representative\n", STABILISER);
327    printf("%d. Compute label for standard matrix of subgroup\n",
328           MATRIX_TO_LABEL);
329    printf("%d. Compute standard matrix for subgroup from label\n",
330           LABEL_TO_MATRIX);
331    printf("%d. Find image of allowable subgroup under automorphism\n", IMAGE);
332    printf("%d. Find rank of closure of initial segment subgroup\n",
333           SUBGROUP_RANK);
334    printf("%d. List representative and orbit for supplied label\n", ORBIT_REP);
335    printf("%d. Write compact descriptions of generated groups to file\n",
336           COMPACT_DESCRIPTION);
337    printf("%d. Find automorphism classes of elements of vector space\n",
338           AUT_CLASSES);
339    printf("%d. Exit to main p-group generation menu\n", MAX_INTERACTIVE_OPTION);
340 }
341 
orbit_option(int option,int ** perms,int ** a,int ** b,char ** c,int ** orbit_length,struct pga_vars * pga)342 void orbit_option(int option,
343                   int **perms,
344                   int **a,
345                   int **b,
346                   char **c,
347                   int **orbit_length,
348                   struct pga_vars *pga)
349 {
350    int t;
351    Logical soluble_group;
352    /*    FILE * file; */
353 
354 
355    if (option != COMBINATION && option != STANDARDISE) {
356       query_solubility(pga);
357       if (pga->soluble)
358          query_space_efficiency(pga);
359       else
360          pga->space_efficient = FALSE;
361       query_orbit_information(pga);
362    } else if (option == COMBINATION) {
363       pga->print_orbit_summary = FALSE;
364       pga->print_orbits = FALSE;
365    } else if (option == STANDARDISE) {
366       pga->print_orbit_summary = FALSE;
367       pga->print_orbits = FALSE;
368    }
369 
370    soluble_group = (pga->soluble || pga->Degree == 1 || pga->nmr_of_perms == 0);
371 
372    if (!pga->space_efficient) {
373       t = runTime();
374       if (soluble_group)
375          compute_orbits(a, b, c, perms, pga);
376       else
377          insoluble_compute_orbits(a, b, c, perms, pga);
378       if (option != COMBINATION && option != STANDARDISE) {
379          t = runTime() - t;
380          printf("Time to compute orbits is %.2f seconds\n", t * CLK_SCALE);
381       }
382    }
383 
384    /* if in soluble portion of combination, we do not need to
385       set up representives */
386    if (option == COMBINATION && pga->soluble)
387       return;
388 
389    *orbit_length = find_orbit_reps(*a, *b, pga);
390 
391    if (pga->print_orbit_summary)
392       orbit_summary(*orbit_length, pga);
393    /*   file = OpenFile ("COUNT", "a+");
394         fprintf (file, "%d,\n", pga->nmr_orbits);
395    */
396 }
397 
stabiliser_option(int option,int *** auts,int ** perms,int * a,int * b,char * c,int * orbit_length,struct pga_vars * pga,struct pcp_vars * pcp)398 void stabiliser_option(int option,
399                        int ***auts,
400                        int **perms,
401                        int *a,
402                        int *b,
403                        char *c,
404                        int *orbit_length,
405                        struct pga_vars *pga,
406                        struct pcp_vars *pcp)
407 {
408    int t;
409    int i;
410    /*Logical soluble_group;*/
411    FILE *OutputFile;
412    char *StartName;
413    int *rep;
414    int *length;
415    rep = allocate_vector(1, 1, 0);
416    length = allocate_vector(1, 1, 0);
417 
418    t = runTime();
419 
420    query_solubility(pga);
421    if (pga->soluble)
422       query_space_efficiency(pga);
423    else
424       pga->space_efficient = FALSE;
425    /*soluble_group = (pga->soluble || pga->Degree == 1 || pga->nmr_of_perms == 0);*/
426 
427    query_terminal(pga);
428    query_exponent_law(pga);
429    query_metabelian_law(pga);
430    query_group_information(pga->p, pga);
431    query_aut_group_information(pga);
432    StartName = GetString("Enter output file name: ");
433    OutputFile = OpenFileOutput(StartName);
434 
435    pga->final_stage = (pga->q == pga->multiplicator_rank);
436    pga->nmr_of_descendants = 0;
437    pga->nmr_of_capables = 0;
438 
439    if (option == STABILISER) {
440       read_value(TRUE, "Input the orbit representative: ", &rep[1], 1);
441       /* find the length of the orbit having this representative */
442       for (i = 1; i <= pga->nmr_orbits && pga->rep[i] != rep[1]; ++i)
443          ;
444       if (pga->rep[i] == rep[1])
445          length[1] = orbit_length[i];
446       else {
447          printf("%d is not an orbit representative\n", rep[1]);
448          return;
449       }
450    }
451 
452    if (option == STABILISER)
453       setup_reps(rep,
454                  1,
455                  length,
456                  perms,
457                  a,
458                  b,
459                  c,
460                  auts,
461                  OutputFile,
462                  OutputFile,
463                  pga,
464                  pcp);
465    else
466       setup_reps(pga->rep,
467                  pga->nmr_orbits,
468                  orbit_length,
469                  perms,
470                  a,
471                  b,
472                  c,
473                  auts,
474                  OutputFile,
475                  OutputFile,
476                  pga,
477                  pcp);
478 
479    /*
480      #if defined (GAP_LINK)
481      if (!soluble_group)
482      QuitGap ();
483      #endif
484      */
485 
486    RESET(OutputFile);
487 
488    printf("Time to process representative is %.2f seconds\n",
489           (runTime() - t) * CLK_SCALE);
490 }
491 
492 
493 /* list orbit representatives as words subject to the supplied map */
494 
list_word(struct pga_vars * pga,struct pcp_vars * pcp)495 int list_word(struct pga_vars *pga, struct pcp_vars *pcp)
496 {
497    register int i, j;
498    int start_length;
499 
500    int start[100];
501    int word[100];
502 
503    int **S;
504    int index;
505    int *subset;
506    int length = 0;
507    register int k, r;
508    register int lastg = pcp->lastg;
509 
510    start_length = 0;
511    /*
512      read_value (TRUE, "Input length of initial segment: ", &start_length, 0);
513      for (i = 1; i <= start_length; ++i)
514      scanf ("%d", &start[i]);
515      */
516 
517    for (r = 1; r <= pga->nmr_orbits; ++r) {
518 
519       S = label_to_subgroup(&index, &subset, pga->rep[r], pga);
520 
521       print_matrix(S, pga->s, pga->q);
522 
523       for (i = 0; i < pga->q; ++i) {
524 
525          if (1 << i & pga->list[index])
526             continue;
527 
528          for (j = 1; j <= lastg; ++j)
529             word[j] = 0;
530 
531          for (j = 0; j < pga->s; ++j)
532             if (S[j][i] != 0)
533                word[pcp->ccbeg + subset[j]] = pga->p - S[j][i];
534 
535          word[pcp->ccbeg + i] = 1;
536 
537          print_array(word, pcp->ccbeg, lastg + 1);
538 
539          length = 0;
540          for (k = pcp->ccbeg; k <= lastg; ++k)
541             if (word[k] != 0)
542                ++length;
543 
544          printf("%d\n", length + start_length);
545          for (k = 1; k <= start_length; ++k)
546             printf("%d 1 ", start[k]);
547 
548          for (k = pcp->ccbeg; k <= lastg; ++k)
549             if (word[k] != 0)
550                printf("%d %d ", k, word[k]);
551          printf("\n");
552       }
553    }
554 
555    return 0;
556 }
557