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