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