diff --git a/gap/semigroups/semifp.gi b/gap/semigroups/semifp.gi index 19c1ad0bb..532c7edc9 100644 --- a/gap/semigroups/semifp.gi +++ b/gap/semigroups/semifp.gi @@ -298,7 +298,7 @@ function(S) spos := Position(sgens, sgens[i]); mpos := Position(mgens, sgens[i], start[spos]); lookup[i] := mpos; - if spos <> fail then + if mpos <> fail then start[spos] := mpos; fi; od; @@ -541,3 +541,99 @@ IsCollsElms, [IsFpSemigroup, IsElementOfFpSemigroup], function(S, x) return SEMIGROUPS.ExtRepObjToWord(ExtRepOfObj(x)); end); + +# This method is based on the following paper +# Presentations of Factorizable Inverse Monoids +# David Easdown, James East, and D. G. FitzGerald +# July 19, 2004 +InstallMethod(IsomorphismFpSemigroup, +"for an inverse partial perm semigroup", +[IsPartialPermSemigroup and IsInverseActingSemigroupRep], +function(M) + local add_to_odd_positions, S, SS, G, GG, s, g, F, rels, fam, alpha, + beta, lhs, rhs, map, H, o, comp, U, rhs_list, conj, MF, T, inv, rel, x, y, m, + i; + + if not IsFactorisableInverseMonoid(M) then + TryNextMethod(); + fi; + + add_to_odd_positions := function(list, s) + list{[1, 3 .. Length(list) - 1]} := list{[1, 3 .. Length(list) - 1]} + s; + return list; + end; + + S := Semigroup(IdempotentGeneratedSubsemigroup(M)); + SS := GeneratorsOfSemigroup(S); + G := GroupOfUnits(M); + GG := GeneratorsOfSemigroup(G); + s := Length(GeneratorsOfSemigroup(S)); + g := Length(GeneratorsOfSemigroup(G)); + + F := FreeSemigroup(s + g); + rels := []; + fam := ElementsFamily(FamilyObj(F)); + + # R_S - semigroup relations for the idempotent generated subsemigroup + alpha := IsomorphismFpSemigroup(S); + for rel in RelationsOfFpSemigroup(Image(alpha)) do + Add(rels, [ObjByExtRep(fam, ExtRepOfObj(rel[1])), + ObjByExtRep(fam, ExtRepOfObj(rel[2]))]); + od; + + # R_G - semigroup relations for the group of units + beta := IsomorphismFpSemigroup(G); + for rel in RelationsOfFpSemigroup(Image(beta)) do + lhs := add_to_odd_positions(ShallowCopy(ExtRepOfObj(rel[1])), s); + rhs := add_to_odd_positions(ShallowCopy(ExtRepOfObj(rel[2])), s); + Add(rels, [ObjByExtRep(fam, lhs), ObjByExtRep(fam, rhs)]); + od; + + # R_product - see page 4 of the paper + for x in [1 .. s] do + for y in [1 .. g] do + rhs := Factorization(S, SS[x] ^ (GG[y] ^ -1)); + Add(rels, [F.(s + y) * F.(x), + EvaluateWord(GeneratorsOfSemigroup(F), rhs) * F.(s + y)]); + od; + od; + + map := InverseGeneralMapping(IsomorphismPermGroup(G)); + H := Source(map); + o := Enumerate(LambdaOrb(M)); + #R_tilde - see page 4 of the paper + for m in [2 .. Length(OrbSCC(o))] do + comp := OrbSCC(o)[m]; + U := SmallGeneratingSet(Stabilizer(H, + PartialPerm(o[comp[1]], o[comp[1]]), + OnRight)); + + for i in comp do + rhs_list := Factorization(S, PartialPerm(o[i], o[i])); + rhs := EvaluateWord(GeneratorsOfSemigroup(F), rhs_list); + conj := MappingPermListList(o[comp[1]], o[i]); + for x in List(U, x -> x ^ conj) do + lhs := ShallowCopy(rhs_list); + Append(lhs, Factorization(G, x ^ map) + s); + Add(rels, [EvaluateWord(GeneratorsOfSemigroup(F), lhs), rhs]); + od; + od; + od; + + # Relation to indentify One(G) and One(S) + Add(rels, [EvaluateWord(GeneratorsOfSemigroup(F), + Factorization(G, One(G)) + s), + EvaluateWord(GeneratorsOfSemigroup(F), + Factorization(S, One(S)))]); + + MF := F / rels; # FpSemigroup which is isomorphic to M, with different gens. + fam := ElementsFamily(FamilyObj(MF)); + T := Semigroup(Concatenation(SS, GG)); # M with isomorphic generators to MF + + map := x -> ElementOfFpSemigroup(fam, EvaluateWord(GeneratorsOfSemigroup(F), + Factorization(T, x))); + inv := x -> EvaluateWord(GeneratorsOfSemigroup(T), + SEMIGROUPS.ExtRepObjToWord(ExtRepOfObj(x))); + + return MagmaIsomorphismByFunctionsNC(M, MF, map, inv); +end); diff --git a/tst/standard/semifp.tst b/tst/standard/semifp.tst index 29005b9c0..c191e1ec3 100644 --- a/tst/standard/semifp.tst +++ b/tst/standard/semifp.tst @@ -2060,6 +2060,67 @@ gap> SEMIGROUPS.ExtRepObjToString([100, 1]); Error, SEMIGROUPS.ExtRepObjToString: the maximum value in an odd position of t\ he argument must be at most 52, +# Test IsomorphismFpSemigroup (for factorizable inverse monoids) +gap> S := SymmetricInverseMonoid(4);; +gap> iso := IsomorphismFpSemigroup(S);; +gap> BruteForceIsoCheck(iso); +true +gap> BruteForceInverseCheck(iso); +true +gap> S := InverseSemigroup( +> [PartialPerm([1, 2, 3, 4, 5, 6, 7, 8], [2, 4, 8, 6, 3, 1, 5, 7]), +> PartialPerm([1, 2, 3, 4, 5, 6, 7, 8], [3, 5, 4, 7, 6, 8, 1, 2]), +> PartialPerm([1, 2, 3, 4, 5, 6, 7, 8], [4, 6, 7, 1, 8, 2, 3, 5]), +> PartialPerm([], [])]);; +gap> iso := IsomorphismFpSemigroup(S);; +gap> BruteForceIsoCheck(iso); +true +gap> BruteForceInverseCheck(iso); +true +gap> S := InverseSemigroup( +> [PartialPerm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [9, 10, 8, 2, 1, 7, 5, 4, 6, 3]), +> PartialPerm([1, 2, 3, 4, 5, 6, 7, 8, 9, 10], [10, 9, 3, 6, 5, 2, 8, 1, 4, 7]), +> PartialPerm([], [])]);; +gap> iso := IsomorphismFpSemigroup(S);; +gap> BruteForceIsoCheck(iso); +true +gap> BruteForceInverseCheck(iso); +true +gap> tst := [InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [4, 5, 2, 3, 1]), +> PartialPerm([1, 3], [1, 3])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4], [1, 2, 3, 4]), +> PartialPerm([1, 2, 3, 4, 5], [3, 1, 5, 4, 2])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [5, 4, 2, 3, 1]), +> PartialPerm([1, 2, 4], [1, 2, 4])]), +> InverseMonoid([PartialPerm([1, 2, 5], [2, 1, 5]), +> PartialPerm([1, 2], [1, 2])]), +> InverseMonoid([PartialPerm([1, 2, 3], [1, 4, 5]), +> PartialPerm([1, 2, 3, 4, 5], [1, 5, 4, 2, 3])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [3, 1, 5, 4, 2]), +> PartialPerm([1, 2, 3, 4, 5], [5, 1, 3, 4, 2])]), +> InverseMonoid([PartialPerm([1, 2, 5], [2, 3, 5]), +> PartialPerm([1, 2, 3, 5], [2, 3, 1, 5])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [4, 2, 3, 1, 5]), +> PartialPerm([1, 2, 3, 4, 5], [5, 3, 2, 1, 4])]), +> InverseMonoid([PartialPerm([1, 2, 3, 5], [2, 1, 3, 5]), +> PartialPerm([1, 2, 3, 5], [5, 2, 1, 3])]), +> InverseMonoid([PartialPerm([1, 2, 3], [5, 4, 1]), +> PartialPerm([1, 2, 3, 4, 5], [2, 3, 5, 1, 4])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [4, 3, 5, 2, 1]), +> PartialPerm([1, 2, 4, 5], [5, 4, 2, 1]), +> PartialPerm([1, 4], [3, 2]), PartialPerm([1, 2, 3, 4, 5], [2, 3, 5, 1, 4]), +> PartialPerm([1, 2, 5], [2, 3, 4])]), +> InverseMonoid([PartialPerm([1, 2, 3, 4, 5], [2, 4, 1, 5, 3]), +> PartialPerm([1, 3, 4], [2, 1, 3]), +> PartialPerm([1, 2, 3, 4, 5], [4, 1, 2, 5, 3]), PartialPerm([1, 3], [5, 4]), +> PartialPerm([1, 3, 5], [2, 4, 1])])];; +gap> ForAll(tst, IsFactorisableInverseMonoid); +true +gap> ForAll(tst, S -> BruteForceIsoCheck(IsomorphismFpSemigroup(S))); +true +gap> ForAll(tst{[1 .. 10]}, S -> BruteForceInverseCheck(IsomorphismFpSemigroup(S))); +true + #T# SEMIGROUPS_UnbindVariables gap> Unbind(BruteForceInverseCheck); gap> Unbind(BruteForceIsoCheck);