GAP 4.8.9 installation with standard packages -- copy to your CoCalc project to get it
############################################################################# ## #W ExtAutom.gi FGA package Christian Sievers ## ## Methods to create and compute with extended inverse automata ## #Y 2003 - 2016 ## InstallValue( FGA_FreeGroupForGenerators, FreeGroup(infinity) ); InstallValue( FGA_One, One(FGA_FreeGroupForGenerators) ); InstallGlobalFunction( FGA_newstateX, function() return (rec (delta:=[], deltainv:=[], sndsig:=[], sndsiginv:=[])); end ); InstallGlobalFunction( FGA_connectposX, function(s1, s2, g, sndsig, sndsiginv) s1.delta[g] := s2; s2.deltainv[g] := s1; s1.sndsig[g] := sndsig; s2.sndsiginv[g] := sndsiginv; end ); InstallGlobalFunction( FGA_connectX, function(s1, s2, g, sndsig) if g>0 then FGA_connectposX(s1, s2, g, sndsig, sndsig^-1); else FGA_connectposX(s2, s1, -g, sndsig^-1, sndsig); fi; end ); InstallGlobalFunction( FGA_defineX, function(state, gen) local nstate; nstate := FGA_newstateX(); FGA_connectX(state, nstate, gen, FGA_One); # nstate.W := state.W * gen return nstate; end ); # active InstallGlobalFunction( FGA_findX, function(s) local sndsig; sndsig := FGA_One; while IsBound(s.isnow) do sndsig := sndsig * s.sndcoinc; s := s.isnow; od; return rec(state:=s, sndcoinc:=sndsig); # todo: path compression end ); InstallGlobalFunction( FGA_mergeX, function(s1, A, s2, B, Q) local s, C; s1 := FGA_findX(s1); s2 := FGA_findX(s2); if IsNotIdenticalObj(s1.state,s2.state) then if IsBound(s2.state.isinitial) then # don't mess with the initial state s := s1; s1 := s2; s2 := s; C := A; A := B; B := C; fi; s2.state.isnow := s1.state; s2.state.sndcoinc := (B*s2.sndcoinc)^-1*A*s1.sndcoinc; Add(Q,s2.state); fi; end ); InstallGlobalFunction( FGA_coincidenceX, function(s1, A, s2, B) local Q, s, g, s0, s01, delta, deltainv; Q := []; FGA_mergeX(s1, A, s2, B, Q); for s in Q do delta := ShallowCopy(s.delta); for g in BoundPositions(delta) do Unbind(delta[g].deltainv[g]); od; deltainv := ShallowCopy(s.deltainv); for g in BoundPositions(deltainv) do Unbind(deltainv[g].delta[g]); od; for g in BoundPositions(delta) do s0 := FGA_findX(s); s01 := FGA_findX(delta[g]); if IsBound(s0.state.delta[g]) then FGA_mergeX(s01.state, s.sndsig[g]*s01.sndcoinc, s0.state.delta[g], s0.sndcoinc*s0.state.sndsig[g], Q); elif IsBound(s01.state.deltainv[g]) then FGA_mergeX(s0.state, s.sndsig[g]^-1*s0.sndcoinc, s01.state.deltainv[g], s01.sndcoinc*s01.state.sndsiginv[g], Q); else FGA_connectX(s0.state, s01.state, g, s0.sndcoinc^-1*s.sndsig[g]*s01.sndcoinc); fi; od; for g in BoundPositions(deltainv) do s0 := FGA_findX(s); s01 := FGA_findX(deltainv[g]); if IsBound(s0.state.deltainv[g]) then FGA_mergeX(s01.state, s.sndsiginv[g]*s01.sndcoinc, s0.state.deltainv[g], s0.sndcoinc*s0.state.sndsiginv[g], Q); elif IsBound(s01.state.delta[g]) then FGA_mergeX(s0.state, s.sndsiginv[g]^-1*s0.sndcoinc, s01.state.delta[g], s01.sndcoinc*s01.state.sndsig[g], Q); else FGA_connectX(s01.state, s0.state, g, s01.sndcoinc^-1*s.sndsiginv[g]^-1*s0.sndcoinc); fi; od; od; end ); InstallGlobalFunction( FGA_atfX, function(l, lx, p) if IsBound(l[p]) then return rec(state:=l[p], sndsig:=lx[p]); else return fail; fi; end ); InstallGlobalFunction( FGA_deltaX, function(state, gen) if gen>0 then return FGA_atfX(state.delta, state.sndsig, gen); else return FGA_atfX(state.deltainv, state.sndsiginv, -gen); fi; end ); InstallGlobalFunction( FGA_stepX, function(r, gen) local res; res := FGA_deltaX(r.state, gen); if res <> fail then res.sndsig := r.sndsig * res.sndsig; fi; return res; end ); InstallGlobalFunction( FGA_deltasX, function(state, genlist) return IteratedF(genlist, FGA_stepX, rec(state:=state, sndsig:=FGA_One)); end ); InstallGlobalFunction( FGA_traceX, function(s,w) local i, s1; s := rec(state := s, sndsig := FGA_One); s1 := s; i := 1; while i <= Length(w) and s1 <> fail do s := s1; s1 := FGA_stepX(s, w[i]); i := i+1; od; if s1 = fail then return rec(state:=s.state, index:=i-1, sndsig:=s.sndsig); else return rec(state:=s1.state, index:=i, sndsig:=s1.sndsig); fi; end ); InstallGlobalFunction( FGA_backtraceX, function(s,w,j) local i, s1; s := rec(state:=s, sndsig := FGA_One); s1 := s; i := Length(w); while i >= j and s1 <> fail do s := s1; s1 := FGA_stepX(s, -w[i]); i := i-1; od; if s1 = fail then return rec(state:=s.state, index:=i+1, sndsig:=s.sndsig ); else return rec(state:=s1.state, index:=i, sndsig:=s1.sndsig); fi; end ); InstallGlobalFunction( FGA_insertgeneratorX, function(s, g, sndgen) local i, t, bt, s1, s2; t := FGA_traceX(s, g); bt := FGA_backtraceX(s, g, t.index); s1 := t.state; s2 := bt.state; if t.index > bt.index then # trace complete FGA_coincidenceX(s1, sndgen^-1*t.sndsig, s2, bt.sndsig); else if IsIdenticalObj(s1, s2) then while g[t.index] = -g[bt.index] do s1 := FGA_defineX(s1, g[t.index]); t.index := t.index+1; bt.index := bt.index - 1; od; s2 := s1; fi; for i in [t.index .. bt.index-1] do s1 := FGA_defineX(s1, g[i]); od; FGA_connectX(s1, s2, g[bt.index], t.sndsig^-1*sndgen*bt.sndsig); fi; return FGA_find(s); end ); InstallGlobalFunction( FGA_fromgeneratorsX, function(gens) local gen, i, autom; i := 1; autom := FGA_newstateX(); autom.isinitial := true; for gen in gens do autom := FGA_insertgeneratorX(autom, gen, FGA_FreeGroupForGenerators.(i) ); i := i+1; od; return autom; end ); InstallGlobalFunction( FGA_FromGroupWithGeneratorsX, function( G ) return FGA_fromgeneratorsX( List ( GeneratorsOfGroup ( G ), LetterRepAssocWord )); end ); InstallGlobalFunction( FGA_AsWordLetterRepInGenerators, function( w, A) local res; res := FGA_deltasX( A, w ); if res = fail or IsNotIdenticalObj( res.state, A ) then return fail; else return LetterRepAssocWord( res.sndsig ); fi; end ); ############################################################################# ## #E