GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
#############################################################################
##
#W Intsect.gi FGA package Christian Sievers
##
## Installations for the computation of intersections of free groups
##
#Y 2003 - 2012
##
#############################################################################
##
#F FGA_StateTable( <table>, <i>, <j> )
##
InstallGlobalFunction( FGA_StateTable,
function( t, i, j )
if not IsBound( t[i] ) then
t[i] := [];
fi;
if not IsBound( t[i][j] ) then
t[i][j] := FGA_newstate();
fi;
return t[i][j];
end );
#############################################################################
##
#M Intersection2( <G1>, <G2> )
##
InstallMethod( Intersection2,
"for subgroups of free groups",
IsIdenticalObj,
[ CanComputeWithInverseAutomaton, CanComputeWithInverseAutomaton ],
function( G1, G2 )
local A, t, sl1, sl2, i, nr1, nr2, Q, pair, g, q, q1, q2, bpd, bpdi;
# let the gap lib handle this case:
if IsSubgroupOfWholeGroupByQuotientRep( G1 ) and
IsSubgroupOfWholeGroupByQuotientRep( G2 ) then
TryNextMethod();
fi;
t := [];
i := FGA_StateTable( t, 1, 1 );
sl1 := FGA_States( FreeGroupAutomaton( G1 ) );
sl2 := FGA_States( FreeGroupAutomaton( G2 ) );
Q := [ [1,1] ];
for pair in Q do
q1 := sl1[ pair[1] ];
q2 := sl2[ pair[2] ];
q := FGA_StateTable( t, pair[1], pair[2] );
for g in Difference(
Intersection( BoundPositions( q1.delta ),
BoundPositions( q2.delta ) ),
BoundPositions( q.delta ) ) do
nr1 := q1.delta[g].nr;
nr2 := q2.delta[g].nr;
FGA_connectpos( q, FGA_StateTable( t, nr1, nr2 ), g );
Add( Q, [ nr1, nr2 ] );
od;
for g in Difference(
Intersection( BoundPositions( q1.deltainv ),
BoundPositions( q2.deltainv ) ),
BoundPositions( q.deltainv ) ) do
nr1 := q1.deltainv[g].nr;
nr2 := q2.deltainv[g].nr;
FGA_connectpos( FGA_StateTable( t, nr1, nr2 ), q, g );
Add( Q, [ nr1, nr2 ] );
od;
bpd := BoundPositions( q.delta );
bpdi := BoundPositions( q.deltainv );
while Size( bpd ) + Size( bpdi ) = 1 and
IsNotIdenticalObj( q, i ) do
if Size( bpd ) = 1 then
g := bpd[ 1 ];
q := q.delta[ g ];
Unbind( q.deltainv[ g ] );
else
g := bpdi[ 1 ];
q := q.deltainv[ g ];
Unbind( q.delta[ g ] );
fi;
bpd := BoundPositions( q.delta );
bpdi := BoundPositions( q.deltainv );
od;
od;
A := Objectify( NewType( FamilyObj( G1 ), IsSimpleInvAutomatonRep ),
rec( initial:=i, terminal:=i,
group := TrivialSubgroup( G1 ) ) );
return AsGroup( A );
end );
#############################################################################
##
#F FGA_TrySetRepTable( <t>, <i>, <j>, <r>, <g> )
##
InstallGlobalFunction( FGA_TrySetRepTable,
function( t, i, j, r, g )
local rx;
if not IsBound( t[i] ) then
t[i] := [];
fi;
if not IsBound( t[i][j] ) then
rx := ShallowCopy( r );
Add( rx, g );
t[i][j] := rx;
return rx;
else
return fail;
fi;
end );
#############################################################################
##
#F FGA_GetNr ( <state>, <statelist> )
##
InstallGlobalFunction( FGA_GetNr,
function( q, sl )
if not IsBound( q.nr ) then
Add( sl, q );
q.nr := Size( sl );
elif not IsBound( sl[ q.nr ] ) then
sl[ q.nr ] := q;
fi;
return q.nr;
end );
#############################################################################
##
#F FGA_FindRepInIntersection ( <A1>, <t1>, <A2>, <t2> )
##
InstallGlobalFunction( FGA_FindRepInIntersection,
function( A1, t1, A2, t2 )
local tab, sl1, sl2, Q, pair, g, q1, nr1, q2, nr2, r, rx;
sl1 := [];
sl2 := [];
q1 := A1!.initial;
q2 := A2!.initial;
if IsIdenticalObj( q1, t1) and
IsIdenticalObj( q2, t2) then
return [];
fi;
nr1 := FGA_GetNr( q1, sl1 );
nr2 := FGA_GetNr( q2, sl2 );
tab := [];
tab [ nr1 ] := [];
tab [ nr1 ][ nr2 ] := []; # empty word at initial state
Q := [ [ nr1, nr2 ] ];
for pair in Q do
q1 := sl1[ pair[1] ];
q2 := sl2[ pair[2] ];
r := tab [ pair[1] ] [ pair[2] ];
for g in Intersection( BoundPositions( q1.delta ),
BoundPositions( q2.delta ) ) do
nr1 := FGA_GetNr(q1.delta[g], sl1);
nr2 := FGA_GetNr(q2.delta[g], sl2);
rx := FGA_TrySetRepTable( tab, nr1, nr2, r, g );
if rx <> fail then
if IsIdenticalObj(sl1[ nr1 ], t1) and
IsIdenticalObj(sl2[ nr2 ], t2) then
return rx;
fi;
Add( Q, [ nr1, nr2 ] );
fi;
od;
for g in Intersection( BoundPositions( q1.deltainv ),
BoundPositions( q2.deltainv ) ) do
nr1 := FGA_GetNr(q1.deltainv[g], sl1);
nr2 := FGA_GetNr(q2.deltainv[g], sl2);
rx := FGA_TrySetRepTable( tab, nr1, nr2, r, -g );
if rx <> fail then
if IsIdenticalObj(sl1[ nr1 ], t1) and
IsIdenticalObj(sl2[ nr2 ], t2) then
return rx;
fi;
Add( Q, [ nr1, nr2 ] );
fi;
od;
od;
return fail;
end );
#############################################################################
##
#E