Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve support for quotient semigroups #841

Merged
merged 1 commit into from
Jun 15, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion gap/attributes/attr.gd
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,12 @@ DeclareAttribute("NormalizedPrincipalFactor", IsGreensDClass);
DeclareAttribute("MultiplicativeZero", IsSemigroup);
DeclareAttribute("LengthOfLongestDClassChain", IsSemigroup);

# We use IsListOrCollection here because some collections of semigroup
# generators (such as elements/congruence classes in a quotient semigroup) do
# not satisfy IsMultiplicativeElementCollection (although the classes
# themselves do satisfy IsMultiplicativeElement).
DeclareAttribute("SmallSemigroupGeneratingSet",
IsMultiplicativeElementCollection);
IsListOrCollection);
DeclareAttribute("SmallMonoidGeneratingSet",
IsMultiplicativeElementWithOneCollection);
DeclareAttribute("SmallInverseSemigroupGeneratingSet",
Expand Down
5 changes: 2 additions & 3 deletions gap/attributes/attr.gi
Original file line number Diff line number Diff line change
Expand Up @@ -288,9 +288,8 @@ InstallMethod(NormalizedPrincipalFactor, "for a Green's D-class",

# different method for ideals, not yet implemented

InstallMethod(SmallSemigroupGeneratingSet,
"for a multiplicative element collection",
[IsMultiplicativeElementCollection],
InstallMethod(SmallSemigroupGeneratingSet, "for a list or collection",
[IsListOrCollection],
function(coll)
if Length(coll) < 2 then
return coll;
Expand Down
7 changes: 7 additions & 0 deletions gap/congruences/cong.gi
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,13 @@ InstallMethod(CongruenceHandednessString, "for a left congruence",
InstallMethod(CongruenceHandednessString, "for a 2-sided congruence",
[IsMagmaCongruence and IsSemigroupCongruence], C -> "2-sided");

# This is required for QuotientSemigroups and their subsemigroups.
InstallImmediateMethod(CanEasilyCompareElements,
IsCongruenceClass and HasEquivalenceClassRelation, 0,
function(C)
return CanUseLibsemigroupsCongruence(EquivalenceClassRelation(C));
end);

########################################################################
# Flexible functions for creating congruences
########################################################################
Expand Down
24 changes: 24 additions & 0 deletions gap/congruences/conginv.gi
Original file line number Diff line number Diff line change
Expand Up @@ -561,3 +561,27 @@ function(S)

return InverseSemigroupCongruenceByKernelTraceNC(S, ker, traceBlocks);
end);

# TODO(later) this is a completely generic version implementation, surely we
# can do better than this!

InstallMethod(GeneratingPairsOfMagmaCongruence,
"for inverse semigroup congruence by kernel and trace",
[IsInverseSemigroupCongruenceByKernelTrace],
function(C)
local CC, pairs, class, i, j;

CC := SemigroupCongruenceByGeneratingPairs(Source(C), []);
for class in EquivalenceRelationPartition(C) do
for i in [1 .. Length(class) - 1] do
for j in [i + 1 .. Length(class)] do
if not [class[i], class[j]] in CC then
pairs := GeneratingPairsOfSemigroupCongruence(CC);
pairs := Concatenation(pairs, [[class[i], class[j]]]);
CC := SemigroupCongruenceByGeneratingPairs(Source(C), pairs);
fi;
od;
od;
od;
return pairs;
end);
19 changes: 19 additions & 0 deletions gap/congruences/congpairs.gi
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,25 @@ InstallImmediateMethod(GeneratingPairsOfLeftRightOrTwoSidedCongruence,
0,
GeneratingPairsOfRightMagmaCongruence);

# Some types of congruences (such as CongruenceByKernelAndTrace) do not know
# their generating pairs by default, and hence we require the following methods
# in addition to the immediate methods above.

InstallMethod(GeneratingPairsOfLeftRightOrTwoSidedCongruence,
"for a right semigroup congruence",
[IsRightSemigroupCongruence],
GeneratingPairsOfRightMagmaCongruence);

InstallMethod(GeneratingPairsOfLeftRightOrTwoSidedCongruence,
"for a left semigroup congruence",
[IsLeftSemigroupCongruence],
GeneratingPairsOfLeftMagmaCongruence);

InstallMethod(GeneratingPairsOfLeftRightOrTwoSidedCongruence,
"for a semigroup congruence",
[IsSemigroupCongruence],
GeneratingPairsOfMagmaCongruence);

InstallMethod(AsSemigroupCongruenceByGeneratingPairs,
"for semigroup congruence",
[IsSemigroupCongruence],
Expand Down
4 changes: 2 additions & 2 deletions gap/congruences/congpart.gi
Original file line number Diff line number Diff line change
Expand Up @@ -281,8 +281,8 @@ end);
# This is declared only for CanComputeEquivalenceRelationPartition because no
# other types of congruence have CongruenceTestMembershipNC implemented.
InstallMethod(\in,
"for pair of mult. elt. and left, right, or 2-sided congruence",
[IsMultiplicativeElementCollection, CanComputeEquivalenceRelationPartition],
"for pair of elements and left, right, or 2-sided congruence",
[IsListOrCollection, CanComputeEquivalenceRelationPartition],
function(pair, C)
local S, string;

Expand Down
88 changes: 44 additions & 44 deletions gap/libsemigroups/cong.gi
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,6 @@

## This file contains the interface to libsemigroups Congruence objects.

# TODO: A method for MeetXSemigroupCongruences

###########################################################################
# Categories + properties + true methods
###########################################################################
Expand All @@ -33,7 +31,6 @@

InstallImmediateMethod(CanUseLibsemigroupsCongruence,
IsLeftRightOrTwoSidedCongruence
and HasGeneratingPairsOfLeftRightOrTwoSidedCongruence
and HasRange,
0,
C -> CanUseFroidurePin(Range(C))
Expand All @@ -43,32 +40,12 @@ InstallImmediateMethod(CanUseLibsemigroupsCongruence,
or (HasIsFreeMonoid(Range(C))
and IsFreeMonoid(Range(C))));

InstallImmediateMethod(CanUseLibsemigroupsCongruence,
IsRMSCongruenceByLinkedTriple,
0,
ReturnFalse);

InstallImmediateMethod(CanUseLibsemigroupsCongruence,
IsRZMSCongruenceByLinkedTriple,
0,
ReturnFalse);

InstallImmediateMethod(CanUseLibsemigroupsCongruence,
IsSimpleSemigroupCongruence,
0,
ReturnFalse);

InstallImmediateMethod(CanUseLibsemigroupsCongruence,
IsInverseSemigroupCongruenceByKernelTrace,
0,
ReturnFalse);

InstallMethod(CanUseLibsemigroupsCongruence,
"for a left, right, or 2-sided congruence that can compute partition",
[CanComputeEquivalenceRelationPartition],
ReturnFalse);

# TODO(now) remove CanUseLibsemigroupsCongruences?
# TODO(later) remove CanUseLibsemigroupsCongruences?

# A semigroup satisfies this property if its congruences should belong to
# CanUseLibsemigroupsCongruence.
Expand All @@ -84,6 +61,8 @@ InstallTrueMethod(CanUseLibsemigroupsCongruences,
HasIsFreeSemigroup and IsFreeSemigroup);
InstallTrueMethod(CanUseLibsemigroupsCongruences,
HasIsFreeMonoid and IsFreeMonoid);
InstallTrueMethod(CanUseLibsemigroupsCongruence,
IsInverseSemigroupCongruenceByKernelTrace);

###########################################################################
# Functions/methods that are declared in this file and that use the
Expand Down Expand Up @@ -164,6 +143,13 @@ function(S)
return libsemigroups.Congruence.make_from_froidurepin_pbr;
end);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a quotient semigroup and CanUseLibsemigroupsCongruences",
[IsQuotientSemigroup and CanUseLibsemigroupsCongruences],
function(S)
return libsemigroups.Congruence.make_from_froidurepinbase;
end);

# Get the libsemigroups::Congruence object associated to a GAP object

BindGlobal("LibsemigroupsCongruence",
Expand Down Expand Up @@ -205,6 +191,7 @@ function(C)
libsemigroups.Congruence.add_runner(CC, tc);
factor := MinimalFactorization;
else
# TODO(QUOTIENT): What about if IsQuotientSemigroup(Range(C))?
# Shouldn't be possible to reach the next line, and can't currently test it
TryNextMethod();
fi;
Expand Down Expand Up @@ -242,10 +229,10 @@ end);
########################################################################

InstallMethod(CongruenceLessNC,
"for CanUseLibsemigroupsCongruence and two mult. elements",
[CanUseLibsemigroupsCongruence,
IsMultiplicativeElement,
IsMultiplicativeElement],
"for CanUseLibsemigroupsCongruence and two mult. elements",
[CanUseLibsemigroupsCongruence,
IsMultiplicativeElement,
IsMultiplicativeElement],
function(C, elm1, elm2)
local S, pos1, pos2, lookup, word1, word2, CC;

Expand All @@ -261,7 +248,8 @@ function(C, elm1, elm2)
word2 := MinimalFactorization(S, pos2);
fi;
elif IsFpSemigroup(S) or (HasIsFreeSemigroup(S) and IsFreeSemigroup(S))
or IsFpMonoid(S) or (HasIsFreeMonoid(S) and IsFreeMonoid(S)) then
or IsFpMonoid(S) or (HasIsFreeMonoid(S) and IsFreeMonoid(S))
or IsQuotientSemigroup(S) then
word1 := Factorization(S, elm1);
word2 := Factorization(S, elm2);
else
Expand All @@ -277,8 +265,10 @@ end);
# libsemigroups object directly
###########################################################################

InstallMethod(NrEquivalenceClasses, "for CanUseLibsemigroupsCongruence",
[CanUseLibsemigroupsCongruence],
InstallMethod(NrEquivalenceClasses,
"for CanUseLibsemigroupsCongruence with known generating pairs",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence],
function(C)
local number_of_classes, result;
number_of_classes := libsemigroups.Congruence.number_of_classes;
Expand All @@ -290,8 +280,9 @@ function(C)
end);

InstallMethod(CongruenceTestMembershipNC,
"for CanUseLibsemigroupsCongruence and two mult. elements",
[CanUseLibsemigroupsCongruence,
"for CanUseLibsemigroupsCongruence with known gen. pairs and 2 mult. elts",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence,
IsMultiplicativeElement,
IsMultiplicativeElement],
100,
Expand Down Expand Up @@ -321,8 +312,10 @@ function(C, elm1, elm2)
return libsemigroups.Congruence.contains(CC, word1 - 1, word2 - 1);
end);

InstallMethod(EquivalenceRelationPartition, "for CanUseLibsemigroupsCongruence",
[CanUseLibsemigroupsCongruence],
InstallMethod(EquivalenceRelationPartition,
"for CanUseLibsemigroupsCongruence with known generating pairs",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence],
function(C)
local S, CC, ntc, gens, class, i, j;
S := Range(C);
Expand Down Expand Up @@ -357,10 +350,11 @@ function(class1, class2)
local C, word1, word2, CC;

C := EquivalenceClassRelation(class1);
if C <> EquivalenceClassRelation(class2) then
return false;
elif not CanUseLibsemigroupsCongruence(C) then
if not CanUseLibsemigroupsCongruence(C)
or not HasGeneratingPairsOfLeftRightOrTwoSidedCongruence(C) then
TryNextMethod();
elif C <> EquivalenceClassRelation(class2) then
return false;
fi;

word1 := Factorization(Range(C), Representative(class1));
Expand All @@ -369,8 +363,10 @@ function(class1, class2)
return libsemigroups.Congruence.less(CC, word1 - 1, word2 - 1);
end);

InstallMethod(EquivalenceClasses, "for CanUseLibsemigroupsCongruence",
[CanUseLibsemigroupsCongruence],
InstallMethod(EquivalenceClasses,
"for CanUseLibsemigroupsCongruence with known generating pairs",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence],
function(C)
local result, CC, gens, class_index_to_word, rep, i;

Expand All @@ -396,7 +392,9 @@ end);
###########################################################################

InstallMethod(EquivalenceRelationPartitionWithSingletons,
"for CanUseLibsemigroupsCongruence", [CanUseLibsemigroupsCongruence],
"for CanUseLibsemigroupsCongruence with known generating pairs",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence],
function(C)
local part, i, x;
if not IsFinite(Range(C)) then
Expand All @@ -416,8 +414,9 @@ function(C)
end);

InstallMethod(ImagesElm,
"for CanUseLibsemigroupsCongruence and a multiplicative element",
[CanUseLibsemigroupsCongruence, IsMultiplicativeElement],
"for CanUseLibsemigroupsCongruence with known gen. pairs and a mult. elt.",
[CanUseLibsemigroupsCongruence and
HasGeneratingPairsOfLeftRightOrTwoSidedCongruence, IsMultiplicativeElement],
function(cong, elm)
local lookup, id, part, pos;

Expand All @@ -429,7 +428,8 @@ function(cong, elm)
elif IsFpSemigroup(Range(cong))
or (HasIsFreeSemigroup(Range(cong)) and IsFreeSemigroup(Range(cong)))
or IsFpMonoid(Range(cong))
or (HasIsFreeSemigroup(Range(cong)) and IsFreeMonoid(Range(cong))) then
or (HasIsFreeSemigroup(Range(cong)) and IsFreeMonoid(Range(cong)))
or IsQuotientSemigroup(Range(cong)) then
part := EquivalenceRelationPartition(cong);
pos := PositionProperty(part, l -> [elm, l[1]] in cong);
if pos = fail then
Expand Down
Loading