GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
#W selfsimgroup.gd automgrp package Yevgen Muntyan
#W Dmytro Savchuk
## automgrp v 1.3
##
#Y Copyright (C) 2003 - 2016 Yevgen Muntyan, Dmytro Savchuk
##
#############################################################################
##
#C IsSelfSimGroup( <G> )
##
## The category of groups whose generators are defined using wreath recursion
## (elements from category `IsSelfSim'). These groups need not be self-similar.
##
DeclareSynonym("IsSelfSimGroup", IsSelfSimCollection and IsGroup);
InstallTrueMethod(IsTreeAutomorphismCollection, IsSelfSimGroup);
InstallTrueMethod(IsInvertibleSelfSimCollection, IsSelfSimGroup);
#############################################################################
##
#O SelfSimilarGroup( <string>[, <bind_vars>] )
#O SelfSimilarGroup( <list>[, <names>, <bind_vars>] )
#O SelfSimilarGroup( <automaton>[, <bind_vars>] )
##
## Creates the self-similar group generated by the wreath recursion, described by <string>
## or <list>, or given by the argument <automaton>.
##
## The argument <string> is a conventional notation of the form
## `name1=(word11,word12,...,word1d)perm1, name2=...'
## where each `name\*' is a name of a state, `word\*' is an associative word
## over the alphabet consisting of all `name\*', and each `perm\*' is a
## permutation written in {\GAP} notation. Trivial permutations may be
## omitted. This function ignores whitespace, and states may be separated
## by commas or semicolons.
##
## The argument <list> is a list consisting of $n$ entries corresponding to $n$ generators of the group.
## Each entry is of the form $[a_1,\.\.\.,a_d,p]$,
## where $d \geq 2$ is the size of the alphabet the group acts on, $a_i$ are lists
## acceptable by `AssocWordByLetterRep' (e.g. if the names of generators are `x', `y' and `z',
## then `[1, 1, -2, -2, 1, 3]' will produce `x^2*y^-2*x*z')
## representing the sections of the corresponding generator at all vertices of the first level of the tree;
## and $p$ from `SymmetricGroup(<d>)' describes the action of the corresponding generator on the
## alphabet.
##
## The optional argument <names> must be a list of names of generators of the group.
## These names are used to display the elements of the resulting group.
##
## If the optional argument <bind_vars> is `false' the names of generators of the group are not assigned
## to the global variables. The default value is `true'. One can use
## `AssignGeneratorVariables' function to assign these names later, if they were not assigned
## when the group was created.
##
## \beginexample
## gap> SelfSimilarGroup("a=(a*b, b^-1), b=(1, b^2*a)(1,2)");
## < a, b >
## gap> SelfSimilarGroup("a=(b,a,a^-1)(2,3), b=(1,a*b,b)(1,2,3)");
## < a, b >
## gap> A := MealyAutomaton("f0=(f0,f0)(1,2),f1=(f1,f0)");
## <automaton>
## gap> SelfSimilarGroup(A);
## < f0, f1 >
## \endexample
## In the second form of this operation the definition of the first group
## looks like
## \beginexample
## gap> SelfSimilarGroup([[ [1,2], [-2], ()], [ [], [2,2,1], (1,2) ]], ["a","b"]);
## < a, b >
## \endexample
##
DeclareOperation("SelfSimilarGroup", [IsList]);
DeclareOperation("SelfSimilarGroup", [IsList, IsList]);
DeclareOperation("SelfSimilarGroup", [IsList, IsBool]);
DeclareOperation("SelfSimilarGroup", [IsList, IsList, IsBool]);
DeclareOperation("SelfSimilarGroup", [IsMealyAutomaton]);
DeclareOperation("SelfSimilarGroup", [IsMealyAutomaton, IsBool]);
#############################################################################
##
#P IsGroupOfSelfSimFamily( <G> )
##
## Whether group <G> is the whole group generated by the automaton used to
## construct elements of <G>.
##
DeclareProperty("IsGroupOfSelfSimFamily", IsSelfSimGroup);
InstallTrueMethod(IsSelfSimilar, IsGroupOfSelfSimFamily);
#############################################################################
##
#A UnderlyingFreeSubgroup(<G>)
##
DeclareAttribute("UnderlyingFreeSubgroup", IsSelfSimGroup, "mutable");
#############################################################################
##
#P IsSelfSimilarGroup (<G>)
##
## is `true' if <G> is created using the command `SelfSimilarGroup' ("SelfSimilarGroup")
## or if the generators of <G> coincide with the generators of the corresponding family, and `false' otherwise.
## To test whether <G> is self-similar use `IsSelfSimilar' ("IsSelfSimilar") command.
##
DeclareProperty("IsSelfSimilarGroup", IsSelfSimGroup);
InstallTrueMethod(IsGroupOfSelfSimFamily, IsSelfSimilarGroup);
#############################################################################
##
#A MihailovaSystem(<G>)
##
DeclareAttribute("MihailovaSystem", IsSelfSimGroup, "mutable");
#############################################################################
##
#A IsomorphicAutomGroup(<G>)
##
## In case <G> is finite-state tries to compute a group generated by automata, isomorphic to <G>,
## which is a subgroup of `UnderlyingAutomatonGroup'(<G>) (see "UnderlyingAutomatonGroup").
## The natural isomorphism between <G> and `IsomorphicAutomGroup'(<G>) is stored in the
## attribute `MonomorphismToAutomatonGroup'(<G>) ("MonomorphismToAutomatonGroup").
## In some cases it may be useful to check if <G> is finite.
## \beginexample
## gap> R := SelfSimilarGroup("a=(a^-1*b,b^-1*a)(1,2), b=(a^-1,b^-1)");
## < a, b >
## gap> UR := UnderlyingAutomatonGroup(R);
## < a1, a2, a4, a5 >
## gap> IR := IsomorphicAutomGroup(R);
## < a1, a5 >
## gap> hom := MonomorphismToAutomatonGroup(R);
## MappingByFunction( < a, b >, < a1, a5 >, function( a ) ... end, function( b ) \
## ... end )
## gap> (a*b)^hom;
## a1*a5
## gap> PreImagesRepresentative(hom, last);
## a*b
## gap> List(GeneratorsOfGroup(UR), x -> PreImagesRepresentative(hom, x));
## [ a, a^-1*b, b^-1*a, b ]
## \endexample
##
## All these operations work also for the subgroups of groups generated by `SelfSimilarGroup'.
## ("SelfSimilarGroup").
## \beginexample
## gap> T := Group([b*a, a*b]);
## < b*a, a*b >
## gap> IT := IsomorphicAutomGroup(T);
## < a1, a4 >
## \endexample
## Note, that different groups have different `UnderlyingAutomGroup' attributes. For example,
## the generator `a1' of group `IT' above is different from the generator `a1' of group `IR'.
##
DeclareAttribute("IsomorphicAutomGroup", IsSelfSimGroup, "mutable");
#############################################################################
##
#A UnderlyingAutomatonGroup(<G>)
##
## In case <G> is finite-state returns a self-similar closure of <G> as a group
## generated by automaton.
## The natural monomorphism from <G> and `UnderlyingAutomatonGroup'(<G>) is stored in the
## attribute `MonomorphismToAutomatonGroup'(<G>) ("MonomorphismToAutomatonGroup"). If
## <G> is created by `SelfSimilarGroup' (see "SelfSimilarGroup"), then the self-similar closure
## of <G> coincides with <G>, so one can use `MonomorphismToAutomatonGroup'(<G>) to
## get preimages of elements of `UnderlyingAutomatonGroup'(<G>) in <G>. See the example for
## `IsomorphicAutomGroup' ("IsomorphicAutomGroup").
##
DeclareAttribute("UnderlyingAutomatonGroup", IsSelfSimGroup, "mutable");
#############################################################################
##
#A MonomorphismToAutomatonGroup(<G>)
##
## In case <G> is finite-state returns a monomorphism from <G> into `UnderlyingAutomatonGroup'(<G>)
## (see "UnderlyingAutomatonGroup"). If <G> is created by `SelfSimilarGroup' (see "SelfSimilarGroup"),
## then one can use `MonomorphismToAutomatonGroup'(<G>) to
## get preimages of elements of `UnderlyingAutomatonGroup'(<G>) in <G>. See the example for
## `IsomorphicAutomGroup' ("IsomorphicAutomGroup").
##
DeclareAttribute("MonomorphismToAutomatonGroup", IsSelfSimGroup, "mutable");
#############################################################################
##
#A GroupOfSelfSimFamily(<G>)
##
DeclareAttribute("GroupOfSelfSimFamily", IsSelfSimGroup);
#E