1#############################################################################
2##
3#W  automgroup.gi             automgrp package                 Yevgen Muntyan
4#W                                                             Dmytro Savchuk
5##
6#Y  Copyright (C) 2003 - 2018 Yevgen Muntyan, Dmytro Savchuk
7##
8
9
10###############################################################################
11##
12#M  AutomatonGroup(<list>)
13##
14InstallMethod(AutomatonGroup, "for [IsList]", [IsList],
15function(list)
16  return AutomatonGroup(list, false);
17end);
18
19
20###############################################################################
21##
22#M  AutomatonGroup(<list>, <bind_vars>)
23##
24InstallMethod(AutomatonGroup, "for [IsList, IsBool]", [IsList, IsBool],
25function(list, bind_vars)
26  if not AG_IsCorrectAutomatonList(list, true) then
27    Error("in AutomatonGroup(IsList, IsBool):\n",
28          "  given list is not a correct list representing automaton\n");
29  fi;
30
31  return GroupOfAutomFamily(AutomFamily(list, bind_vars));
32end);
33
34
35###############################################################################
36##
37#M  AutomatonGroup(<list>, <names>)
38##
39InstallMethod(AutomatonGroup, "for [IsList, IsList]", [IsList, IsList],
40function(list, names)
41  return AutomatonGroup(list, names, AG_Globals.bind_vars_autom_family);
42end);
43
44
45###############################################################################
46##
47#M  AutomatonGroup(<list>, <names>, <bind_vars>)
48##
49InstallMethod(AutomatonGroup,
50              "for [IsList, IsList, IsBool]", [IsList, IsList, IsBool],
51function(list, names, bind_vars)
52  if not AG_IsCorrectAutomatonList(list, true) then
53    Error("error in AutomatonGroup(IsList, IsList, IsBool):\n",
54          "  given list is not a correct list representing automaton\n");
55  fi;
56
57  return GroupOfAutomFamily(AutomFamily(list, names, bind_vars));
58end);
59
60
61###############################################################################
62##
63#M  AutomatonGroup(<string>)
64#M  AutomatonGroup(<string>, <bind_vars>)
65##
66InstallMethod(AutomatonGroup, "for [IsString]", [IsString],
67function(string)
68  return AutomatonGroup(string, AG_Globals.bind_vars_autom_family);
69end);
70
71InstallMethod(AutomatonGroup, "for [IsString, IsBool]", [IsString, IsBool],
72function(string, bind_vars)
73  local s;
74  s := AG_ParseAutomatonString(string);
75  return AutomatonGroup(s[2], s[1], bind_vars);
76end);
77
78
79InstallMethod(AutomatonGroup, "for [IsMealyAutomaton]", [IsMealyAutomaton],
80function(A)
81  if not IsInvertible(A) then
82    Error("Automaton <A> is not invertible");
83  fi;
84  return AutomatonGroup(AutomatonList(A), A!.states);
85end);
86
87InstallMethod(AutomatonGroup, "for [IsMealyAutomaton, IsBool]", [IsMealyAutomaton, IsBool],
88function(A, bind_vars)
89  if not IsInvertible(A) then
90    Error("Automaton <A> is not invertible");
91  fi;
92  return AutomatonGroup(AutomatonList(A), A!.states, bind_vars);
93end);
94
95
96###############################################################################
97##
98#M  GroupOfAutomFamily(<G>)
99##
100InstallMethod(GroupOfAutomFamily, "for [IsAutomGroup]",
101                   [IsAutomGroup],
102function(G)
103  return GroupOfAutomFamily(UnderlyingAutomFamily(G));
104end);
105
106
107###############################################################################
108##
109#M  IsGroupOfAutomFamily(<G>)
110##
111InstallMethod(IsGroupOfAutomFamily, "for [IsAutomGroup]",
112              [IsAutomGroup],
113function(G)
114  return G = GroupOfAutomFamily(G);
115end);
116
117
118###############################################################################
119##
120#M  UseSubsetRelation(<G>)
121##
122InstallMethod(UseSubsetRelation,
123              "for [IsAutomGroup, IsAutomGroup]",
124              [IsAutomGroup, IsAutomGroup],
125function(super, sub)
126  ## the full group is self similar, so if <super> is smaller than the full
127  ##  group then sub is smaller either
128  if HasIsGroupOfAutomFamily(super) then
129    if not IsGroupOfAutomFamily(super) then
130      SetIsGroupOfAutomFamily(sub, false); fi; fi;
131  TryNextMethod();
132end);
133
134
135###############################################################################
136##
137#M  __AG_SubgroupOnLevel(<G>, <gens>, <level>)
138##
139InstallMethod(__AG_SubgroupOnLevel, [IsAutomGroup,
140                                    IsList and IsTreeAutomorphismCollection,
141                                    IsPosInt],
142function(G, gens, level)
143  local overgroup;
144
145  if IsEmpty(gens) or (Length(gens) = 1 and IsOne(gens[1])) then
146    return TrivialSubgroup(G);
147  fi;
148
149  if HasIsGroupOfAutomFamily(G) and IsGroupOfAutomFamily(G) then
150    overgroup := G;
151  else
152    overgroup := GroupOfAutomFamily(UnderlyingAutomFamily(G));
153  fi;
154
155  return SubgroupNC(overgroup, gens);
156end);
157
158InstallOtherMethod(__AG_SubgroupOnLevel, [IsAutomGroup, IsList and IsEmpty, IsPosInt],
159function(G, gens, level)
160  return TrivialSubgroup(G);
161end);
162
163InstallMethod(__AG_SubgroupOnLevel, [IsTreeAutomorphismGroup,
164                                    IsList and IsInvertibleAutomCollection,
165                                    IsPosInt],
166function(G, gens, level)
167  local overgroup;
168
169  overgroup := GroupOfAutomFamily(FamilyObj(gens[1]));
170
171  if Length(gens) = 1 and IsOne(gens[1]) then
172    return TrivialSubgroup(overgroup);
173  fi;
174
175  return SubgroupNC(overgroup, gens);
176end);
177
178InstallMethod(__AG_SimplifyGroupGenerators, [IsList and IsInvertibleAutomCollection],
179function(gens)
180  local words, fam;
181
182  if IsEmpty(gens) then
183    return [];
184  fi;
185
186  fam := FamilyObj(gens[1]);
187  words := FreeGeneratorsOfGroup(Group(List(gens, a -> a!.word)));
188
189  if fam!.use_rws and not IsEmpty(words) then
190    words := AG_ReducedForm(fam!.rws, words);
191    if not IsEmpty(words) then
192      words := FreeGeneratorsOfGroup(Group(words));
193    fi;
194  fi;
195
196  if IsEmpty(words) then
197    return [];
198  fi;
199
200  return List(words, w -> Autom(w, fam));
201end);
202
203###############################################################################
204##
205#M  PrintObj(<G>)
206##
207InstallMethod(PrintObj, "for [IsAutomatonGroup]",
208              [IsAutomatonGroup],
209function(G)
210  Print("AutomatonGroup(\"", String(G), "\")");
211end);
212
213
214###############################################################################
215##
216#M  Display(<G>)
217##
218InstallMethod(Display, "for [IsAutomGroup]",
219              [IsAutomGroup],
220function(G)
221  local i, gens, printone;
222
223  printone := function(a)
224    Print(a, " = ", Decompose(a));
225  end;
226
227  gens := GeneratorsOfGroup(G);
228  if gens = [] then Print("< >"); fi;
229  if Length(gens) = 1 then
230    Print("< "); printone(gens[1]); Print(" >");
231  else
232    Print("< "); printone(gens[1]); Print(", \n");
233    for i in [2..Length(gens)-1] do
234      Print("  "); printone(gens[i]); Print(", \n");
235    od;
236    Print("  "); printone(gens[Length(gens)]); Print(" >");
237  fi;
238end);
239
240
241#############################################################################
242##
243#M  String(<G>)
244##
245InstallMethod(String, "for [IsAutomGroup]", [IsAutomGroup],
246function(G)
247  local i, gens, formatone, s;
248
249  formatone := function(a)
250    return Concatenation(String(a), " = ", String(Decompose(a)));
251  end;
252
253  gens := GeneratorsOfGroup(G);
254
255  s := "";
256  for i in [1..Length(gens)] do
257    Append(s, formatone(gens[i]));
258    if i <> Length(gens) then
259      Append(s, ", ");
260    fi;
261  od;
262
263  return s;
264end);
265
266###############################################################################
267##
268#M  ViewObj(<G>)
269##
270InstallMethod(ViewObj, "for [IsAutomGroup]",
271              [IsAutomGroup],
272function(G)
273  local i, gens;
274  gens := List(GeneratorsOfGroup(G), g -> Word(g));
275  if gens = [] then Print("< >"); fi;
276  Print("< ");
277  for i in [1..Length(gens)-1] do
278    if IsOne(gens[i]) then
279      Print(AG_Globals.identity_symbol, ", ");
280    else
281      Print(gens[i], ", ");
282    fi;
283  od;
284  if IsOne(gens[Length(gens)]) then
285    Print(AG_Globals.identity_symbol, " >");
286  else
287    Print(gens[Length(gens)], " >");
288  fi;
289end);
290
291
292###############################################################################
293##
294#M  MihailovaSystem(G)
295##
296##  TODO XXX test it
297##
298InstallMethod(MihailovaSystem, "for [IsAutomatonGroup]", [IsAutomatonGroup],
299function (G)
300  local gens, mih, mih_gens, i;
301
302  if not IsActingOnBinaryTree(G) then
303    Error("MihailovaSystem(IsAutomGroup):\n  sorry, group is not acting on binary tree\n");
304  fi;
305  if not IsFractalByWords(G) then
306    Info(InfoAutomGrp, 1, "given group is not IsFractalByWords");
307    return fail;
308  fi;
309
310  gens := GeneratorsOfGroup(StabilizerOfFirstLevel(G));
311  mih := AG_ComputeMihailovaSystemPairs(List(gens, a -> StatesWords(a)));
312
313  if mih = fail then
314    return fail;
315  elif not mih[3] then
316    return gens;
317  fi;
318
319  mih_gens := [];
320  for i in [1..Length(gens)] do
321    mih_gens[i] := AG_CalculateWord(mih[2][i], gens);
322  od;
323  return mih_gens;
324end);
325
326
327###############################################################################
328##
329#M  IsFractalByWords(G)
330##
331InstallMethod(IsFractalByWords, "for [IsAutomGroup]",
332              [IsAutomGroup],
333function (G)
334  local freegens, stab, i, sym, f;
335
336  sym := GroupWithGenerators(List(GeneratorsOfGroup(G), g -> Perm(g)));
337  if not IsTransitive(sym, [1..DegreeOfTree(G)]) then
338    Info(InfoAutomGrp, 1, "group is not transitive on first level");
339    return false;
340  fi;
341
342  f := GroupWithGenerators(List(GeneratorsOfGroup(G), g -> Word(g)));
343  stab := StabilizerOfFirstLevel(G);
344  stab := List(GeneratorsOfGroup(stab), a -> StatesWords(a));
345
346  for i in [1..DegreeOfTree(G)] do
347    if f <> GroupWithGenerators(List(stab, s -> s[i])) then
348      return false;
349    fi;
350  od;
351  return true;
352end);
353
354
355###############################################################################
356##
357#M  Size(G)
358##
359InstallMethod(Size, "for [IsAutomGroup]", [IsAutomGroup],
360function (G)
361  local f, A, lev;
362  if IsTrivial(G) then
363    Info(InfoAutomGrp, 3, "Size(G): 1, G is trivial");
364    return 1;
365  fi;
366
367  if CanEasilyTestSphericalTransitivity(G) and IsSphericallyTransitive(G) then
368    Info(InfoAutomGrp, 3, "Size(G): infinity, G is spherically transitive");
369    return infinity;
370  fi;
371
372  if IsFractalByWords(G) then
373    Info(InfoAutomGrp, 3, "Size(G): infinity, G is fractal by words");
374    return infinity;
375  fi;
376
377  if HasIsFractal(G) and IsFractal(G) then
378    Info(InfoAutomGrp, 3, "Size(G): infinity, G is fractal");
379    return infinity;
380  fi;
381
382
383  if IsAutomatonGroup(G) then
384    A:=MealyAutomaton(AutomatonList(G));
385    if IsMDTrivial(A) then
386      Info(InfoAutomGrp, 3, "Size(G): automaton generating G is MD-trivial");
387      lev:=LevelOfFaithfulAction(G,infinity);
388      return Size(G);
389    elif (DegreeOfTree(G)=2 or NumberOfStates(A)=2) and IsIRAutomaton(A) then
390      Info(InfoAutomGrp, 3, "Size(G): infinity, G is generated by 2-letter or 2-state not MD-trivial IR-automaton ");
391      return infinity;
392    fi;
393  fi;
394
395  if IsAutomatonGroup(G) and LevelOfFaithfulAction(G,8)<>fail then
396    return Size(G);
397  fi;
398
399  f := FindElementOfInfiniteOrder(G,10,10);
400
401  if HasSize(G) or f <> fail then
402    return Size(G);
403  fi;
404
405  Info(InfoAutomGrp, 1, "You can try to use IsomorphismPermGroup(<G>) or\n",
406                        "   FindElementOfInfiniteOrder(<G>,<length>,<depth>) with bigger bounds");
407  TryNextMethod();
408end);
409
410
411InstallOtherMethod(LevelOfFaithfulAction, "for [IsAutomGroup and IsSelfSimilar]",
412              [IsAutomGroup and IsSelfSimilar,IsCyclotomic],
413function(G,max_lev)
414  local s,s_next,lev;
415  if HasIsFinite(G) and not IsFinite(G) then return fail; fi;
416  if HasLevelOfFaithfulAction(G) then return LevelOfFaithfulAction(G); fi;
417  lev := 0; s := 1; s_next := Size(PermGroupOnLevel(G,1));
418  while s<s_next and lev<max_lev do
419    lev := lev+1;
420    s := s_next;
421    s_next := Size(PermGroupOnLevel(G,lev+1));
422  od;
423  if s = s_next then
424    SetSize(G,s);
425    SetLevelOfFaithfulAction(G,lev);
426    return lev;
427  else
428    return fail;
429  fi;
430end);
431
432
433InstallMethod(LevelOfFaithfulAction, "for [IsAutomGroup and IsSelfSimilar]",
434              [IsAutomGroup and IsSelfSimilar],
435function(G)
436  return LevelOfFaithfulAction(G,infinity);
437end);
438
439
440InstallOtherMethod(IsomorphismPermGroup, "for [IsAutomGroup and IsSelfSimilar,IsCyclotomic]",
441                   [IsAutomGroup and IsSelfSimilar, IsCyclotomic],
442function (G, n)
443  local H, lev;
444  lev := LevelOfFaithfulAction(G, n);
445  if lev <> fail then
446    H := PermGroupOnLevel(G,LevelOfFaithfulAction(G));
447    return AG_GroupHomomorphismByImagesNC(G, H, GeneratorsOfGroup(G), GeneratorsOfGroup(H));
448  fi;
449  return fail;
450end);
451
452
453
454InstallMethod(IsomorphismPermGroup, "for [IsAutomGroup]",
455              [IsAutomGroup], SUM_FLAGS,
456function (G)
457  local H;
458  H := AG_FiniteGroupId(G);
459  return AG_GroupHomomorphismByImagesNC(G, H, GeneratorsOfGroup(G), GeneratorsOfGroup(H));
460end);
461
462
463
464BindGlobal("TestSelfSimilarity",
465function(G)
466  if CanEasilyTestSelfSimilarity(G) then
467    IsSelfSimilar(G);
468    return true;
469  fi;
470
471  if IsTrivial(G) then
472    SetIsSelfSimilar(G, true);
473    return true;
474  fi;
475
476  if HasIsGroupOfAutomFamily(G) and IsGroupOfAutomFamily(G) then
477    SetIsSelfSimilar(G, true);
478    return true;
479  fi;
480
481  if Set(GeneratorsOfGroup(G)) = Set(GeneratorsOfGroup(GroupOfAutomFamily(UnderlyingAutomFamily(G)))) then
482    SetIsSelfSimilar(G, true);
483    return true;
484  fi;
485
486  return false;
487end);
488
489
490###############################################################################
491##
492#M  IsSphericallyTransitive(G)
493##
494InstallMethod(IsSphericallyTransitive, "for [IsAutomGroup]",
495              [IsAutomGroup],
496function (G)
497  local x, rat_gens, abel_hom, lev;
498
499  if DegreeOfTree(G)=1 then
500    Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): true");
501    Info(InfoAutomGrp, 3, "  G acts on 1-ary tree");
502    return true;
503  fi;
504
505
506  if IsFractalByWords(G) then
507    Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): true");
508    Info(InfoAutomGrp, 3, "  G is fractal");
509    return true;
510  fi;
511
512  if IsTrivial(G) then
513    Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): false");
514    Info(InfoAutomGrp, 3, "  G is trivial: G = ", G);
515    return false;
516  fi;
517
518  if HasIsFinite(G) and IsFinite(G) then
519    Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): false");
520    Info(InfoAutomGrp, 3, "  IsFinite(G): G = ", G);
521    return false;
522  fi;
523
524  if DegreeOfTree(G) = 2 and TestSelfSimilarity(G) and IsSelfSimilar(G) then
525    if HasIsFinite(G) and IsFinite(G) = false then
526      Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): true");
527      Info(InfoAutomGrp, 3, "  <G> is infinite self-similar acting on binary tree");
528      return true;
529    fi;
530    if PermGroupOnLevel(G,2) = Group((1,4,2,3)) then
531      Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): true");
532      Info(InfoAutomGrp, 3, "  any element which acts transitively on the first level acts spherically transitively");
533      return true;
534    fi;
535  fi;
536
537  for lev in [1..8] do
538    if not IsTransitiveOnLevel(G,lev) then
539      Info(InfoAutomGrp, 3, "IsSphericallyTransitive(G): false");
540      Info(InfoAutomGrp, 3, "  the group does not act transitively on level ", lev);
541      return false;
542    fi;
543  od;
544
545  TryNextMethod();
546end);
547
548
549###############################################################################
550##
551#M  DiagonalPower(<G>, <n>)
552##
553InstallOtherMethod( DiagonalPower,
554                    "for [IsAutomGroup and IsGroupOfAutomFamily, IsPosInt]",
555                    [IsAutomGroup and IsGroupOfAutomFamily, IsPosInt],
556function(G, n)
557  return DiagonalPower(UnderlyingAutomFamily(G), n);
558end);
559
560
561###############################################################################
562##
563#M  MultAutomAlphabet(<G>, <n>)
564##
565InstallOtherMethod( MultAutomAlphabet,
566                    "for [IsAutomGroup and IsGroupOfAutomFamily, IsPosInt]",
567                    [IsAutomGroup and IsGroupOfAutomFamily, IsPosInt],
568function(G, n)
569  return MultAutomAlphabet(UnderlyingAutomFamily(G), n);
570end);
571
572
573###############################################################################
574##
575#M  \= (<G>, <H>)
576##
577InstallMethod(\=, "for [IsAutomGroup, IsAutomGroup]",
578              IsIdenticalObj, [IsAutomGroup, IsAutomGroup],
579function(G, H)
580  local fgens1, fgens2, fam;
581
582  if HasIsGroupOfAutomFamily(G) and HasIsGroupOfAutomFamily(H) then
583    if IsGroupOfAutomFamily(G) <> IsGroupOfAutomFamily(H) then
584      Info(InfoAutomGrp, 3, "G = H: false, exactly one is GroupOfAutomFamily");
585      return false;
586    fi;
587    if IsGroupOfAutomFamily(G) then
588      Info(InfoAutomGrp, 3, "G = H: true, both are GroupOfAutomFamily");
589      return true;
590    fi;
591  fi;
592
593  fgens1 := List(GeneratorsOfGroup(G), g -> Word(g));
594  fgens2 := List(GeneratorsOfGroup(H), g -> Word(g));
595  fam := UnderlyingAutomFamily(G);
596
597  if fam!.rws <> fail then
598    fgens1 := AG_ReducedForm(fam!.rws, fgens1);
599    fgens2 := AG_ReducedForm(fam!.rws, fgens2);
600  fi;
601
602  if IsEmpty(fgens1) then
603    return ForAll(fgens2, IsOne);
604  elif IsEmpty(fgens2) then
605    return ForAll(fgens1, IsOne);
606  fi;
607
608  if GroupWithGenerators(fgens1) = GroupWithGenerators(fgens2) then
609    Info(InfoAutomGrp, 3, "G = H: true, by subgroups of free group");
610    return true;
611  fi;
612
613  TryNextMethod();
614end);
615
616
617###############################################################################
618##
619#M  IsSubset (<G>, <H>)
620##
621InstallMethod(IsSubset, "for [IsAutomGroup, IsAutomGroup]",
622              IsIdenticalObj, [IsAutomGroup, IsAutomGroup],
623function(G, H)
624  local h, fam, fgens1, fgens2;
625
626  if HasIsGroupOfAutomFamily(G) and IsGroupOfAutomFamily(G) then
627    Info(InfoAutomGrp, 3, "IsSubgroup(G, H): true");
628    Info(InfoAutomGrp, 3, "  G is GroupOfAutomFamily");
629    return true;
630  fi;
631
632  fgens1 := List(GeneratorsOfGroup(G), g -> Word(g));
633  fgens2 := List(GeneratorsOfGroup(H), g -> Word(g));
634  fam := UnderlyingAutomFamily(G);
635
636  if fam!.rws <> fail then
637    fgens1 := AG_ReducedForm(fam!.rws, fgens1);
638    fgens2 := AG_ReducedForm(fam!.rws, fgens2);
639  fi;
640
641  if IsSubgroup(GroupWithGenerators(fgens1), GroupWithGenerators(fgens2)) then
642    Info(InfoAutomGrp, 3, "IsSubgroup(G, H): true");
643    Info(InfoAutomGrp, 3, "  by subgroups of free group");
644    return true;
645  fi;
646
647  TryNextMethod();
648end);
649
650
651###############################################################################
652##
653#M  <g> in <G>
654##
655InstallMethod(\in, "for [IsAutom, IsAutomGroup]",
656              [IsAutom, IsAutomGroup],
657function(g, G)
658  local fam, fgens, w;
659
660  if HasIsGroupOfAutomFamily(G) and IsGroupOfAutomFamily(G) then
661    return true;
662  fi;
663
664  fgens := List(GeneratorsOfGroup(G), g -> Word(g));
665  w := Word(g);
666
667  fam := UnderlyingAutomFamily(G);
668
669  if fam!.rws <> fail then
670    fgens := AG_ReducedForm(fam!.rws, fgens);
671    if IsEmpty(fgens) then
672      return IsOne(g);
673    fi;
674    w := AG_ReducedForm(fam!.rws, w);
675  fi;
676
677  if w in GroupWithGenerators(fgens) then
678    Info(InfoAutomGrp, 3, "g in G: true");
679    Info(InfoAutomGrp, 3, "  by elements of free group");
680    Info(InfoAutomGrp, 3, "  g = ", g, "; G = ", G);
681    return true;
682  fi;
683
684  TryNextMethod();
685end);
686
687
688###############################################################################
689##
690#M  Random(<G>)
691##
692InstallMethodWithRandomSource(Random, "for a random source and [IsAutomGroup]",
693              [IsRandomSource, IsAutomGroup],
694function(rs, G)
695  local F, gens, pi;
696
697  if IsTrivial(G) then
698    return One(G);
699  elif IsAutomatonGroup(G) then
700    return Autom(Random(rs, UnderlyingFreeGroup(G)), UnderlyingAutomFamily(G));
701  else
702    gens := GeneratorsOfGroup(G);
703    F := FreeGroup(Length(gens));
704    pi := GroupHomomorphismByImagesNC(F, G,  GeneratorsOfGroup(F), gens);
705    return Random(rs, F)^pi;
706  fi;
707end);
708
709
710###############################################################################
711##
712#M  UnderlyingFreeSubgroup(<G>)
713##
714InstallMethod(UnderlyingFreeSubgroup, "for [IsAutomGroup]",
715              [IsAutomGroup],
716function(G)
717  local f;
718  if HasIsGroupOfAutomFamily(G) and IsGroupOfAutomFamily(G) then
719    return UnderlyingFreeGroup(G);
720  fi;
721  f := Subgroup(UnderlyingFreeGroup(G), UnderlyingFreeGenerators(G));
722  if f = UnderlyingFreeGroup(G) then
723    SetIsGroupOfAutomFamily(G, true);
724  fi;
725  return f;
726end);
727
728
729###############################################################################
730##
731#M  UnderlyingFreeGenerators(<G>)
732##
733InstallMethod(UnderlyingFreeGenerators, "for [IsAutomGroup]",
734              [IsAutomGroup],
735function(G)
736  return List(GeneratorsOfGroup(G), g -> Word(g));
737end);
738
739
740###############################################################################
741##
742#M  TrivialSubmagmaWithOne(<G>)
743##
744InstallMethod(TrivialSubmagmaWithOne, "for [IsAutomGroup]",
745              [IsAutomGroup],
746function(G)
747  return Subgroup(G, [One(G)]);
748end);
749
750
751###############################################################################
752##
753#M  IsAutomatonGroup(<G>)
754##
755InstallImmediateMethod(IsAutomatonGroup, IsAutomGroup, 0,
756function(G)
757  local fam;
758  fam := UnderlyingAutomFamily(G);
759  return fam!.numstates = 0 or
760         GeneratorsOfGroup(G) = fam!.automgens{[1..fam!.numstates]};
761end);
762
763
764###############################################################################
765##
766#M  AutomatonList(<G>)
767##
768InstallMethod(AutomatonList, "for [IsAutomGroup]",
769              [IsAutomGroup],
770function(G)
771  if IsAutomatonGroup(G) then
772    return AutomatonList(GroupOfAutomFamily(UnderlyingAutomFamily(G)));
773  else
774    Error("Group <G> is not necessarily generated by automaton,");
775  fi;
776end);
777
778
779###############################################################################
780##
781#M  IsSelfSimilar(<G>)
782##
783InstallMethod(IsSelfSimilar, "for [IsAutomGroup]",
784              [IsAutomGroup],
785function(G)
786  local g, i, res;
787  res := true;
788  for g in GeneratorsOfGroup(G) do
789    for i in [1..UnderlyingAutomFamily(G)!.deg] do
790      res := Section(g, i) in G;
791      if res = fail then
792        TryNextMethod();
793      elif not res then
794        return false;
795      fi;
796    od;
797  od;
798  return true;
799end);
800
801
802###############################################################################
803##
804#M  UnderlyingAutomFamily(<G>)
805##
806InstallMethod(UnderlyingAutomFamily, "for [IsAutomGroup]",
807              [IsAutomGroup],
808function(G)
809  return FamilyObj(GeneratorsOfGroup(G)[1]);
810end);
811
812
813###############################################################################
814##
815#M  UnderlyingAutomaton(<G>)
816##
817InstallMethod(UnderlyingAutomaton, "for [IsAutomGroup]",
818              [IsAutomGroup],
819function(G)
820  local fam;
821  fam := UnderlyingAutomFamily(G);
822  return MealyAutomaton(AG_AddInversesList(fam!.automatonlist){[1..fam!.numstates+1]});
823end);
824
825
826#E
827