Skip to content
Draft
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
11 changes: 6 additions & 5 deletions GNUmakefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
#
KEXT_NAME = semigroups

KEXT_CXXFLAGS = @LIBSEMIGROUPS_CFLAGS@ -std=gnu++14 -O3
KEXT_CXXFLAGS = @LIBSEMIGROUPS_CFLAGS@ -std=gnu++17 -O3
KEXT_LDFLAGS = @LIBSEMIGROUPS_RPATH@ @LIBSEMIGROUPS_LIBS@

# configure settings
Expand Down Expand Up @@ -47,10 +47,11 @@ ifdef WITH_INCLUDED_LIBSEMIGROUPS
# FIXME(later) all the include paths should point into bin/include/ and not to
# the sources, or otherwise we should stop make installing into bin
ifdef LIBSEMIGROUPS_HPCOMBI_ENABLED
KEXT_CPPFLAGS += -Ilibsemigroups/extern/HPCombi/include
KEXT_CPPFLAGS += -Ilibsemigroups/extern/HPCombi/include/fallback
KEXT_CPPFLAGS += -Ilibsemigroups/third_party/HPCombi/include
KEXT_CPPFLAGS += -Ilibsemigroups/third_party/HPCombi/third_party/
endif
KEXT_CPPFLAGS += -Ilibsemigroups/extern/fmt-8.0.1/include
KEXT_CPPFLAGS += -Ilibsemigroups/third_party/fmt-11.1.4/include
KEXT_CPPFLAGS += -Ilibsemigroups/third_party/magic_enum-0.9.7/include
KEXT_CPPFLAGS += -Ilibsemigroups/include
endif
KEXT_CPPFLAGS += -DFMT_HEADER_ONLY
Expand Down Expand Up @@ -102,7 +103,7 @@ lint:
etc/cpplint.sh

format:
clang-format -i src/*.*pp
clang-format -i src/*.[hc]

.PHONY: lint format

Expand Down
176 changes: 62 additions & 114 deletions gap/libsemigroups/cong.gi
Original file line number Diff line number Diff line change
Expand Up @@ -69,84 +69,11 @@ InstallTrueMethod(CanUseLibsemigroupsCongruence,
# libsemigroups object directly
###########################################################################

DeclareAttribute("LibsemigroupsCongruenceConstructor",
IsSemigroup and CanUseLibsemigroupsCongruences);

# Construct a libsemigroups::Congruence from some GAP object

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a transformation semigroup with CanUseLibsemigroupsCongruences",
[IsTransformationSemigroup and CanUseLibsemigroupsCongruences],
function(S)
local N;
N := DegreeOfTransformationSemigroup(S);
if N <= 16 and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then
return libsemigroups.Congruence.make_from_froidurepin_leasttransf;
elif N <= 2 ^ 16 then
return libsemigroups.Congruence.make_from_froidurepin_transfUInt2;
elif N <= 2 ^ 32 then
return libsemigroups.Congruence.make_from_froidurepin_transfUInt4;
else
# Cannot currently test the next line
Error("transformation degree is too high!");
fi;
end);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a partial perm semigroup with CanUseLibsemigroupsCongruences",
[IsPartialPermSemigroup and CanUseLibsemigroupsCongruences],
function(S)
local N;
N := Maximum(DegreeOfPartialPermSemigroup(S),
CodegreeOfPartialPermSemigroup(S));
if N <= 16 and IsBound(LIBSEMIGROUPS_HPCOMBI_ENABLED) then
return libsemigroups.Congruence.make_from_froidurepin_leastpperm;
elif N <= 2 ^ 16 then
return libsemigroups.Congruence.make_from_froidurepin_ppermUInt2;
elif N <= 2 ^ 32 then
return libsemigroups.Congruence.make_from_froidurepin_ppermUInt4;
else
# Cannot currently test the next line
Error("partial perm degree is too high!");
fi;
end);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a boolean matrix semigroup with CanUseLibsemigroupsCongruences",
[IsBooleanMatSemigroup and CanUseLibsemigroupsCongruences],
function(S)
if DimensionOfMatrixOverSemiring(Representative(S)) <= 8 then
return libsemigroups.Congruence.make_from_froidurepin_bmat8;
fi;
return libsemigroups.Congruence.make_from_froidurepin_bmat;
end);

# Why does this work for types other than boolean matrices?
InstallMethod(LibsemigroupsCongruenceConstructor,
"for a matrix semigroup with CanUseLibsemigroupsCongruences",
[IsMatrixOverSemiringSemigroup and CanUseLibsemigroupsCongruences],
_ -> libsemigroups.Congruence.make_from_froidurepin_bmat);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a bipartition semigroup with CanUseLibsemigroupsCongruences",
[IsBipartitionSemigroup and CanUseLibsemigroupsCongruences],
_ -> libsemigroups.Congruence.make_from_froidurepin_bipartition);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a PBR semigroup and CanUseLibsemigroupsCongruences",
[IsPBRSemigroup and CanUseLibsemigroupsCongruences],
_ -> libsemigroups.Congruence.make_from_froidurepin_pbr);

InstallMethod(LibsemigroupsCongruenceConstructor,
"for a quotient semigroup and CanUseLibsemigroupsCongruences",
[IsQuotientSemigroup and CanUseLibsemigroupsCongruences],
_ -> libsemigroups.Congruence.make_from_froidurepinbase);

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

BindGlobal("LibsemigroupsCongruence",
function(C)
local S, make, CC, factor, N, tc, table, add_pair, pair;
local S, make, CC, factor, N, tc, cayley_digraph, add_generating_pair, pair;

Assert(1, CanUseLibsemigroupsCongruence(C));

Expand All @@ -160,34 +87,50 @@ function(C)
S := Range(C);
if IsFpSemigroup(S) or (HasIsFreeSemigroup(S) and IsFreeSemigroup(S))
or IsFpMonoid(S) or (HasIsFreeMonoid(S) and IsFreeMonoid(S)) then
make := libsemigroups.Congruence.make_from_fpsemigroup;
CC := make(CongruenceHandednessString(C), LibsemigroupsFpSemigroup(S));
CC := libsemigroups.Congruence.make(
CongruenceHandednessString(C),
LibsemigroupsPresentation(S));
factor := Factorization;
elif CanUseLibsemigroupsFroidurePin(S) then
CC := LibsemigroupsCongruenceConstructor(S)(CongruenceHandednessString(C),
LibsemigroupsFroidurePin(S));
factor := MinimalFactorization;
ErrorNoReturn(
Concatenation(
"constructing LibsemigroupsCongruence from a LibsemigroupsFroidurePin ",
"is not yet implemented"));
# TODO: Implement when FroidurePin_to_Congruence function exists
# Something like this:
# fp := LibsemigroupsFroidurePin(S));
# CC := libsemigroups.FroidurePin_to_Congruence(
# CongruenceHandednessString(C),
# fp,
# fp.right_cayley_graph);
# factor := MinimalFactorization;
elif CanUseGapFroidurePin(S) then
N := Length(GeneratorsOfSemigroup(Range(C)));
tc := libsemigroups.ToddCoxeter.make(CongruenceHandednessString(C));
libsemigroups.ToddCoxeter.set_number_of_generators(tc, N);
if IsRightMagmaCongruence(C) then
table := RightCayleyGraphSemigroup(Range(C)) - 1;
else
table := LeftCayleyGraphSemigroup(Range(C)) - 1;
fi;
libsemigroups.ToddCoxeter.prefill(tc, table);
CC := libsemigroups.Congruence.make_from_table(
CongruenceHandednessString(C), "none");
libsemigroups.Congruence.set_number_of_generators(CC, N);
libsemigroups.Congruence.add_runner(CC, tc);
factor := MinimalFactorization;
ErrorNoReturn(
Concatenation(
"constructing LibsemigroupsCongruence from a GAP FroidurePin is not ",
"yet implemented"));
# TODO: Implement when ToddCoxeter_tox_FroidurePin and
# FroidurePin_to_Congruence are implemented. Something like:
# if IsRightMagmaCongruence(C) then
# cayley_digraph := RightCayleyDigraph(S);
# else
# cayley := LeftCayleyDigraph(S);
# fi;
# tc := libsemigroups.ToddCoxeter.make_from_wordgraph(
# CongruenceHandednessString(C),
# cayley_digraph);
# fp := libsemigroups.ToddCoexeter_to_FroidurePin(tc);
# CC := libsemigroups.FroidurePin_to_Congruence(
# CongruenceHandednessString(C),
# fp,
# fp.right_cayley_graph);
# factor := MinimalFactorization;
else
TryNextMethod();
fi;
add_pair := libsemigroups.Congruence.add_pair;
add_generating_pair := libsemigroups.Congruence.add_generating_pair;
for pair in GeneratingPairsOfLeftRightOrTwoSidedCongruence(C) do
add_pair(CC, factor(S, pair[1]) - 1, factor(S, pair[2]) - 1);
add_generating_pair(CC, factor(S, pair[1]) - 1, factor(S, pair[2]) - 1);
od;
C!.LibsemigroupsCongruence := CC;
return CC;
Expand Down Expand Up @@ -308,16 +251,20 @@ function(C)
local S, CC, ntc, gens, class, i, j;
S := Range(C);
if not IsFinite(S) or CanUseLibsemigroupsFroidurePin(S) then
CC := LibsemigroupsCongruence(C);
ntc := libsemigroups.Congruence.ntc(CC) + 1;
gens := GeneratorsOfSemigroup(S);
for i in [1 .. Length(ntc)] do
class := ntc[i];
for j in [1 .. Length(class)] do
class[j] := EvaluateWord(gens, class[j]);
od;
od;
return ntc;
ErrorNoReturn(
Concatenation(
"computing the non-trivial classes of a Congruence is not yet ",
"implemented"));
# CC := LibsemigroupsCongruence(C);
# ntc := libsemigroups.Congruence.ntc(CC) + 1;
# gens := GeneratorsOfSemigroup(S);
# for i in [1 .. Length(ntc)] do
# class := ntc[i];
# for j in [1 .. Length(class)] do
# class[j] := EvaluateWord(gens, class[j]);
# od;
# od;
# return ntc;
elif CanUseGapFroidurePin(S) then
# in this case libsemigroups.Congruence.ntc doesn't work, because S is not
# represented in the libsemigroups object
Expand Down Expand Up @@ -363,15 +310,16 @@ function(C)
"number of classes");
fi;

result := EmptyPlist(NrEquivalenceClasses(C));
CC := LibsemigroupsCongruence(C);
gens := GeneratorsOfSemigroup(Range(C));
class_index_to_word := libsemigroups.Congruence.class_index_to_word;
for i in [1 .. NrEquivalenceClasses(C)] do
rep := EvaluateWord(gens, class_index_to_word(CC, i - 1) + 1);
result[i] := EquivalenceClassOfElementNC(C, rep);
od;
return result;
ErrorNoReturn("libsemigroups.Congruence has no member 'class_index_to_word'");
# result := EmptyPlist(NrEquivalenceClasses(C));
# CC := LibsemigroupsCongruence(C);
# gens := GeneratorsOfSemigroup(Range(C));
# class_index_to_word := libsemigroups.Congruence.class_index_to_word;
# for i in [1 .. NrEquivalenceClasses(C)] do
# rep := EvaluateWord(gens, class_index_to_word(CC, i - 1) + 1);
# result[i] := EquivalenceClassOfElementNC(C, rep);
# od;
# return result;
end);

###########################################################################
Expand Down
16 changes: 0 additions & 16 deletions gap/libsemigroups/fpsemi.gd

This file was deleted.

8 changes: 5 additions & 3 deletions gap/libsemigroups/froidure-pin.gi
Original file line number Diff line number Diff line change
Expand Up @@ -607,7 +607,7 @@ function(S)
Error("the argument (a semigroup) is not finite");
fi;
F := LibsemigroupsFroidurePin(S);
return FroidurePinMemFnRec(S).left_cayley_graph(F) + 1;
return FroidurePinMemFnRec(S).left_cayley_graph(F);
end);

InstallMethod(LeftCayleyDigraph,
Expand All @@ -634,7 +634,9 @@ function(S)
Error("the argument (a semigroup) is not finite");
fi;
F := LibsemigroupsFroidurePin(S);
return FroidurePinMemFnRec(S).right_cayley_graph(F) + 1;

# No need to add 1 here, since this is handled by to_gap<WordGraph>
return FroidurePinMemFnRec(S).right_cayley_graph(F);
end);

InstallMethod(RightCayleyDigraph,
Expand Down Expand Up @@ -821,7 +823,7 @@ function(S)
product := FroidurePinMemFnRec(S).product_by_reduction;
FroidurePinMemFnRec(S).enumerate(T, N + 1);
else
pos_to_pos_sorted := FroidurePinMemFnRec(S).position_to_sorted_position;
pos_to_pos_sorted := FroidurePinMemFnRec(S).to_sorted_position;
product := FroidurePinMemFnRec(S).fast_product;
fi;
for i in [0 .. N - 1] do
Expand Down
16 changes: 16 additions & 0 deletions gap/libsemigroups/presentation.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
#############################################################################
##
## libsemigroups/presentation.gd
## Copyright (C) 2025 Joseph Edwards
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##

# This file exists to construct a libsemigroups Presentation object for an fp
# semigroup or monoid. The resulting libsemigroups::Presentation object is only
# used to initialize a libsemigroups::Congruence object where most questions
# asked about Presentation/FpMonoids will be answered.

DeclareGlobalFunction("LibsemigroupsPresentation");
26 changes: 14 additions & 12 deletions gap/libsemigroups/fpsemi.gi → gap/libsemigroups/presentation.gi
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
#############################################################################
##
## libsemigroups/fpsemi.gi
## Copyright (C) 2022 James D. Mitchell
## libsemigroups/presentation.gi
## Copyright (C) 2025 Joseph Edwards
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##

InstallGlobalFunction("LibsemigroupsFpSemigroup",
InstallGlobalFunction("LibsemigroupsPresentation",
function(S)
local F, SS, R, add_rule, pair;

Assert(1, IsFpSemigroup(S) or (HasIsFreeSemigroup(S) and IsFreeSemigroup(S))
or IsFpMonoid(S) or (HasIsFreeMonoid(S) and IsFreeMonoid(S)));

if IsBound(S!.LibsemigroupsFpSemigroup)
and IsValidGapbind14Object(S!.LibsemigroupsFpSemigroup) then
return S!.LibsemigroupsFpSemigroup;
if IsBound(S!.LibsemigroupsPresentation)
and IsValidGapbind14Object(S!.LibsemigroupsPresentation) then
return S!.LibsemigroupsPresentation;
fi;
Unbind(S!.LibsemigroupsFpSemigroup);
Unbind(S!.LibsemigroupsPresentation);
if IsFpSemigroup(S) then
F := FreeSemigroupOfFpSemigroup(S);
elif IsFpMonoid(S) then
Expand All @@ -29,25 +29,27 @@ function(S)
F := S;
fi;

SS := libsemigroups.FpSemigroup.make();
libsemigroups.FpSemigroup.set_alphabet(SS, Size(GeneratorsOfSemigroup(S)));
SS := libsemigroups.Presentation.make();
libsemigroups.Presentation.set_alphabet_size(
SS,
Size(GeneratorsOfSemigroup(S)));

if IsMonoid(S) then
# The identity must be 0 so that this corresponds to what happens in
# FroidurePin, where GeneratorsOfSemigroup(S) is used and the identity is
# the first entry.
libsemigroups.FpSemigroup.set_identity(SS, 0);
libsemigroups.Presentation.set_identity(SS, 0);
R := RelationsOfFpMonoid(S);
else
R := RelationsOfFpSemigroup(S);
fi;

add_rule := libsemigroups.FpSemigroup.add_rule;
add_rule := libsemigroups.presentation_add_rule;
for pair in R do
add_rule(SS,
Factorization(F, pair[1]) - 1,
Factorization(F, pair[2]) - 1);
od;
S!.LibsemigroupsFpSemigroup := SS;
S!.LibsemigroupsPresentation := SS;
return SS;
end);
6 changes: 3 additions & 3 deletions gap/libsemigroups/sims1.gi
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ function(S, n, extra, kind)
if not IsEmpty(rules) then
libsemigroups.Presentation.alphabet_from_rules(P);
elif (HasIsFreeMonoid(S) and IsFreeMonoid(S)) or IsFpMonoid(S) then
libsemigroups.Presentation.set_alphabet(
libsemigroups.Presentation.alphabet(
P, [0 .. Size(GeneratorsOfMonoid(S)) - 1]);
elif (HasIsFreeSemigroup(S) and IsFreeSemigroup(S)) or IsFpSemigroup(S) then
libsemigroups.Presentation.set_alphabet(
libsemigroups.Presentation.alphabet(
P, [0 .. Size(GeneratorsOfSemigroup(S)) - 1]);
fi;
libsemigroups.Presentation.validate(P);
Expand All @@ -68,7 +68,7 @@ function(S, n, extra, kind)
if not IsEmpty(extra) then
Q := libsemigroups.Presentation.make();
libsemigroups.Presentation.contains_empty_word(Q, IsMonoid(S));
libsemigroups.Presentation.set_alphabet(Q,
libsemigroups.Presentation.alphabet(Q,
libsemigroups.Presentation.alphabet(P));

for pair in extra do
Expand Down
Loading
Loading