From f430c07c457da2af4531ce10e28e0ef8044065b1 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 7 Feb 2024 16:03:49 +0000 Subject: [PATCH 01/15] Adding Free Semilattice constructor --- gap/semigroups/semicons.gd | 1 + gap/semigroups/semicons.gi | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/gap/semigroups/semicons.gd b/gap/semigroups/semicons.gd index 6a5c16d77..3c22fa675 100644 --- a/gap/semigroups/semicons.gd +++ b/gap/semigroups/semicons.gd @@ -12,6 +12,7 @@ DeclareGlobalFunction("TrivialSemigroup"); DeclareConstructor("TrivialSemigroupCons", [IsSemigroup, IsInt]); DeclareGlobalFunction("RectangularBand"); DeclareConstructor("RectangularBandCons", [IsSemigroup, IsPosInt, IsPosInt]); +DeclareOperation("FreeSemilattice", [IsPosInt]); DeclareGlobalFunction("MonogenicSemigroup"); DeclareConstructor("MonogenicSemigroupCons", [IsSemigroup, IsPosInt, IsPosInt]); DeclareGlobalFunction("ZeroSemigroup"); diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 0c83701a1..0ba6564c6 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -406,6 +406,29 @@ for _IsXSemigroup in ["IsBooleanMatSemigroup", od; Unbind(_IsXSemigroup); +# Free semilattice + +InstallMethod(FreeSemilattice, "for a positive integer", +[IsPosInt], +function(n) + local F, gen, l, i, j, commR, idemR; + F := FreeSemigroup(n); + gen := GeneratorsOfSemigroup(F); + l := Length(gen); + + commR := []; + for i in [1 .. l - 1] do + for j in [i + 1 .. l] do + Add(commR, [gen[i] * gen[j], gen[j] * gen[i]]); + od; + od; + + idemR := List( gen, + x -> [x * x, x] + ); + return F / Concatenation(commR, idemR); +end); + # Zero semigroup: main method InstallGlobalFunction(ZeroSemigroup, From 6a6fcf9525bd25e0ce4d25e6db7041a8d04ab47d Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 7 Feb 2024 17:02:05 +0000 Subject: [PATCH 02/15] For Transformation and PartialPerm Semigroups --- gap/semigroups/semicons.gd | 3 +- gap/semigroups/semicons.gi | 95 ++++++++++++++++++++++++++++++++++++-- 2 files changed, 94 insertions(+), 4 deletions(-) diff --git a/gap/semigroups/semicons.gd b/gap/semigroups/semicons.gd index 3c22fa675..a5e6db18c 100644 --- a/gap/semigroups/semicons.gd +++ b/gap/semigroups/semicons.gd @@ -12,7 +12,8 @@ DeclareGlobalFunction("TrivialSemigroup"); DeclareConstructor("TrivialSemigroupCons", [IsSemigroup, IsInt]); DeclareGlobalFunction("RectangularBand"); DeclareConstructor("RectangularBandCons", [IsSemigroup, IsPosInt, IsPosInt]); -DeclareOperation("FreeSemilattice", [IsPosInt]); +DeclareGlobalFunction("FreeSemilattice"); +DeclareConstructor("FreeSemilatticeCons", [IsPosInt]); DeclareGlobalFunction("MonogenicSemigroup"); DeclareConstructor("MonogenicSemigroupCons", [IsSemigroup, IsPosInt, IsPosInt]); DeclareGlobalFunction("ZeroSemigroup"); diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 0ba6564c6..2e7ef1011 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -406,10 +406,47 @@ for _IsXSemigroup in ["IsBooleanMatSemigroup", od; Unbind(_IsXSemigroup); -# Free semilattice +# Free semilattice: main method -InstallMethod(FreeSemilattice, "for a positive integer", -[IsPosInt], +InstallGlobalFunction(FreeSemilattice, +function(arg...) + local filter, n, S; + + if Length(arg) = 1 then + filter := IsTransformationSemigroup; + n := arg[1]; + elif Length(arg) = 2 then + filter := arg[1]; + n := arg[2]; + fi; + + if not IsPosInt(n) or not IsOperation(filter) then + ErrorNoReturn("the arguments must be a positive integer or a filter ", + "and a positive integer"); + fi; + + S := FreeSemilatticeCons(filter, n); + + SetSize(S, 2^n -1); + # SetIsRectangularBand(S, true); + # SetNrRClasses(S, m); + # SetNrLClasses(S, n); + # if m <> 1 or n <> 1 then + # SetIsGroupAsSemigroup(S, false); + # SetIsZeroSemigroup(S, false); + # SetIsTrivial(S, false); + # fi; + # SetIsRightZeroSemigroup(S, m = 1); + # SetIsLeftZeroSemigroup(S, n = 1); + + return S; +end); + +# Free semilattice: constructors + +InstallMethod(FreeSemilatticeCons, +"for IsFpSemigroup and a pos int", +[IsFpSemigroup, IsPosInt], function(n) local F, gen, l, i, j, commR, idemR; F := FreeSemigroup(n); @@ -429,6 +466,58 @@ function(n) return F / Concatenation(commR, idemR); end); +InstallMethod(FreeSemilatticeCons, +"for IsTransformationSemigroup and a pos int", +[IsTransformationSemigroup, IsPosInt], +function(n) + local gen, i, L; + gen := []; + for i in [1 .. n] do + L := [1 .. n + 1]; + L[i] := n + 1; + Add(gen, Transformation(L)); + od; + return Semigroup(gen); +end); + +InstallMethod(FreeSemilatticeCons, +"for IsPartialPermSemigroup and a pos int", +[IsPartialPermSemigroup, IsPosInt], +function(n) + local gen, i, L; + gen := []; + for i in [1 .. n] do + L := [1 .. n]; + Remove(L, i); + Add(gen, PartialPerm(L, L)); + od; + return Semigroup(gen); +end); + +# Free semilattice: other constructors + +for _IsXSemigroup in ["IsReesMatrixSemigroup", + "IsBipartitionSemigroup", + "IsPBRSemigroup", + "IsBooleanMatSemigroup", + "IsNTPMatrixSemigroup", + "IsMaxPlusMatrixSemigroup", + "IsMinPlusMatrixSemigroup", + "IsTropicalMaxPlusMatrixSemigroup", + "IsTropicalMinPlusMatrixSemigroup", + "IsProjectiveMaxPlusMatrixSemigroup", + "IsIntegerMatrixSemigroup"] do + InstallMethod(FreeSemilatticeCons, + Concatenation("for ", _IsXSemigroup, ", and pos int"), + [ValueGlobal(_IsXSemigroup), IsPosInt], + function(filter, n) + return AsSemigroup(filter, + RectangularBandCons(IsTransformationSemigroup, n)); + end); +od; +Unbind(_IsXSemigroup); + + # Zero semigroup: main method InstallGlobalFunction(ZeroSemigroup, From d952a4ad7896abdaf406009a58503b7d2e141474 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Thu, 8 Feb 2024 13:18:01 +0000 Subject: [PATCH 03/15] Lint --- gap/semigroups/semicons.gi | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 2e7ef1011..3cdcb260b 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -427,7 +427,7 @@ function(arg...) S := FreeSemilatticeCons(filter, n); - SetSize(S, 2^n -1); + SetSize(S, 2 ^ n - 1); # SetIsRectangularBand(S, true); # SetNrRClasses(S, m); # SetNrLClasses(S, n); @@ -444,10 +444,10 @@ end); # Free semilattice: constructors -InstallMethod(FreeSemilatticeCons, +InstallMethod(FreeSemilatticeCons, "for IsFpSemigroup and a pos int", [IsFpSemigroup, IsPosInt], -function(n) +function(_, n) local F, gen, l, i, j, commR, idemR; F := FreeSemigroup(n); gen := GeneratorsOfSemigroup(F); @@ -460,16 +460,14 @@ function(n) od; od; - idemR := List( gen, - x -> [x * x, x] - ); + idemR := List(gen, x -> [x * x, x]); return F / Concatenation(commR, idemR); end); -InstallMethod(FreeSemilatticeCons, +InstallMethod(FreeSemilatticeCons, "for IsTransformationSemigroup and a pos int", [IsTransformationSemigroup, IsPosInt], -function(n) +function(_, n) local gen, i, L; gen := []; for i in [1 .. n] do @@ -480,10 +478,10 @@ function(n) return Semigroup(gen); end); -InstallMethod(FreeSemilatticeCons, +InstallMethod(FreeSemilatticeCons, "for IsPartialPermSemigroup and a pos int", [IsPartialPermSemigroup, IsPosInt], -function(n) +function(_, n) local gen, i, L; gen := []; for i in [1 .. n] do @@ -517,7 +515,6 @@ for _IsXSemigroup in ["IsReesMatrixSemigroup", od; Unbind(_IsXSemigroup); - # Zero semigroup: main method InstallGlobalFunction(ZeroSemigroup, From a15a71374d74d13b0b506e3a657b6af387f30962 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon <86776403+Jun2M@users.noreply.github.com> Date: Sat, 10 Feb 2024 17:47:25 +0000 Subject: [PATCH 04/15] Update semicons.gd Number of arguments error resolved --- gap/semigroups/semicons.gd | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gap/semigroups/semicons.gd b/gap/semigroups/semicons.gd index a5e6db18c..10089096e 100644 --- a/gap/semigroups/semicons.gd +++ b/gap/semigroups/semicons.gd @@ -13,7 +13,7 @@ DeclareConstructor("TrivialSemigroupCons", [IsSemigroup, IsInt]); DeclareGlobalFunction("RectangularBand"); DeclareConstructor("RectangularBandCons", [IsSemigroup, IsPosInt, IsPosInt]); DeclareGlobalFunction("FreeSemilattice"); -DeclareConstructor("FreeSemilatticeCons", [IsPosInt]); +DeclareConstructor("FreeSemilatticeCons", [IsSemigroup, IsPosInt]); DeclareGlobalFunction("MonogenicSemigroup"); DeclareConstructor("MonogenicSemigroupCons", [IsSemigroup, IsPosInt, IsPosInt]); DeclareGlobalFunction("ZeroSemigroup"); From 6bc998937c72a2c8f4f3e1206639e7b4d0194bb8 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Sat, 10 Feb 2024 18:57:01 +0000 Subject: [PATCH 05/15] Add docs and a whole lot of tests --- doc/semicons.xml | 41 ++++++ doc/z-chap07.xml | 1 + gap/semigroups/semicons.gi | 5 +- tst/standard/semigroups/semicons.tst | 188 +++++++++++++++++++++++++++ 4 files changed, 232 insertions(+), 3 deletions(-) diff --git a/doc/semicons.xml b/doc/semicons.xml index a5d10da52..c1267b7f7 100644 --- a/doc/semicons.xml +++ b/doc/semicons.xml @@ -147,6 +147,47 @@ true]]> <#/GAPDoc> +<#GAPDoc Label="FreeSemilattice"> + + + + A free semilattice of n generators. + + + If n is a positive integer, then this function returns a free + semilattice with n generators in the representation given by the + filter filt. + + The optional argument filt may be one of the following: + + IsTransformationSemigroup + (the default, if filt is not specified), + IsPartialPermSemigroup, + IsFpSemigroup, + IsBipartitionSemigroup, + IsPBRSemigroup, + IsBooleanMatSemigroup, + IsNTPMatrixSemigroup, + IsMaxPlusMatrixSemigroup, + IsMinPlusMatrixSemigroup, + IsTropicalMaxPlusMatrixSemigroup, + IsTropicalMinPlusMatrixSemigroup, + IsProjectiveMaxPlusMatrixSemigroup, + IsIntegerMatrixSemigroup. + + + S := FreeSemilattice(IsTransformationSemigroup, 5); + +gap> T := FreeSemilattice(IsPartialPermSemigroup, 3); + +gap> U := FreeSemilattice(IsBooleanMatSemigroup, 4); + +]]> + + +<#/GAPDoc> + <#GAPDoc Label="ZeroSemigroup"> diff --git a/doc/z-chap07.xml b/doc/z-chap07.xml index 8616e149b..ce2b680f9 100644 --- a/doc/z-chap07.xml +++ b/doc/z-chap07.xml @@ -155,6 +155,7 @@ <#Include Label = "TrivialSemigroup"> <#Include Label = "MonogenicSemigroup"> <#Include Label = "RectangularBand"> + <#Include Label = "FreeSemilattice"> <#Include Label = "ZeroSemigroup"> <#Include Label = "LeftZeroSemigroup"> <#Include Label = "BrandtSemigroup"> diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 3cdcb260b..887ec1d45 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -494,8 +494,7 @@ end); # Free semilattice: other constructors -for _IsXSemigroup in ["IsReesMatrixSemigroup", - "IsBipartitionSemigroup", +for _IsXSemigroup in ["IsBipartitionSemigroup", "IsPBRSemigroup", "IsBooleanMatSemigroup", "IsNTPMatrixSemigroup", @@ -510,7 +509,7 @@ for _IsXSemigroup in ["IsReesMatrixSemigroup", [ValueGlobal(_IsXSemigroup), IsPosInt], function(filter, n) return AsSemigroup(filter, - RectangularBandCons(IsTransformationSemigroup, n)); + FreeSemilatticeCons(IsTransformationSemigroup, n)); end); od; Unbind(_IsXSemigroup); diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index 3b5f3f24a..f134caf73 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -497,6 +497,194 @@ gap> S := RectangularBand(IsReesMatrixSemigroup, 5, 5); gap> S := RectangularBand(IsReesMatrixSemigroup, 10, 11); +# constructions: FreeSemilattice: errors +gap> S := FreeSemilattice(0); +Error, the arguments must be a positive integer or a filter and a positive int\ +eger +gap> S := FreeSemilattice(IsPartialPermSemigroup, 0); +Error, the arguments must be a positive integer or a filter and a positive int\ +eger +gap> S := FreeSemilattice(IsPermGroup, 1, 1); +Error, the arguments must be a positive integer or a filter and a positive int\ +eger +gap> S := FreeSemilattice(IsPartialPermSemigroup, true); +Error, the arguments must be a positive integer or a filter and a positive int\ +eger +gap> S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 100); + + +# constructions: FreeSemilattice: known properties and attributes, 17 +gap> S := FreeSemilattice(17);; +gap> HasSize(S); +true +gap> Size(S) = 2 ^ 17 - 1; +true + +# constructions: FreeSemilattice: default +gap> S := FreeSemilattice(1); + +gap> S := FreeSemilattice(2); + +gap> S := FreeSemilattice(5); + +gap> S := FreeSemilattice(21); + + + + The optional argument filt may be one of the following: + + IsTransformationSemigroup + (the default, if filt is not specified), + IsPartialPermSemigroup, + IsFpSemigroup, + IsBipartitionSemigroup, + IsPBRSemigroup, + IsBooleanMatSemigroup, + IsNTPMatrixSemigroup, + IsMaxPlusMatrixSemigroup, + IsMinPlusMatrixSemigroup, + IsTropicalMaxPlusMatrixSemigroup, + IsTropicalMinPlusMatrixSemigroup, + IsProjectiveMaxPlusMatrixSemigroup, + IsIntegerMatrixSemigroup. + + +# constructions: FreeSemilattice: transformation semigroup +gap> S := FreeSemilattice(IsTransformationSemigroup, 1); + +gap> S := FreeSemilattice(IsTransformationSemigroup, 2); + +gap> S := FreeSemilattice(IsTransformationSemigroup, 5); + +gap> S := FreeSemilattice(IsTransformationSemigroup, 11); + + +# constructions: FreeSemilattice: partial perm semigroup +S := FreeSemilattice(IsPartialPermSemigroup, 1); + +S := FreeSemilattice(IsPartialPermSemigroup, 2); + +S := FreeSemilattice(IsPartialPermSemigroup, 5); + +S := FreeSemilattice(IsPartialPermSemigroup, 11); + + +# constructions: FreeSemilattice: bipartition semigroup +S := FreeSemilattice(IsBipartitionSemigroup, 1); + +S := FreeSemilattice(IsBipartitionSemigroup, 2); + +S := FreeSemilattice(IsBipartitionSemigroup, 5); + +S := FreeSemilattice(IsBipartitionSemigroup, 11); + + +# constructions: FreeSemilattice: PBR semigroup +S := FreeSemilattice(IsPBRSemigroup, 1); + +S := FreeSemilattice(IsPBRSemigroup, 2); + +S := FreeSemilattice(IsPBRSemigroup, 5); + +S := FreeSemilattice(IsPBRSemigroup, 11); + +S := FreeSemilattice(IsBooleanMatSemigroup, 1); + +# constructions: FreeSemilattice: Boolean matrix semigroup + +S := FreeSemilattice(IsBooleanMatSemigroup, 2); + +S := FreeSemilattice(IsBooleanMatSemigroup, 5); + +S := FreeSemilattice(IsBooleanMatSemigroup, 11); + + +# constructions: FreeSemilattice: NTP matrix semigroup +S := FreeSemilattice(IsNTPMatrixSemigroup, 1); + +S := FreeSemilattice(IsNTPMatrixSemigroup, 2); + +S := FreeSemilattice(IsNTPMatrixSemigroup, 5); + +S := FreeSemilattice(IsNTPMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: max-plus matrix semigroup +S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 1); + +S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 2); + +S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 5); + +S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: min-plus matrix semigroup +S := FreeSemilattice(IsMinPlusMatrixSemigroup, 1); + +S := FreeSemilattice(IsMinPlusMatrixSemigroup, 2); + +S := FreeSemilattice(IsMinPlusMatrixSemigroup, 5); + +S := FreeSemilattice(IsMinPlusMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: tropical max-plus matrix semigroup +S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 1); + +S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 2); + +S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 5); + +S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: tropical min-plus matrix semigroup +S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 1); + +S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 2); + +S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 5); + +S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: projective max-plus matrix semigroup +S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 1); + +S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 2); + +S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 5); + +S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 11); + + +# constructions: FreeSemilattice: integer matrix semigroup +S := FreeSemilattice(IsIntegerMatrixSemigroup, 1); + +S := FreeSemilattice(IsIntegerMatrixSemigroup, 2); + +S := FreeSemilattice(IsIntegerMatrixSemigroup, 5); + +S := FreeSemilattice(IsIntegerMatrixSemigroup, 11); + + # constructions: ZeroSemigroup: errors gap> S := ZeroSemigroup(0); Error, the arguments must be a positive integer or a filter and a positive int\ From d80fd74dca1265f77e414b714065d9cfe42fbacf Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Sun, 11 Feb 2024 16:50:49 +0000 Subject: [PATCH 06/15] Minor test fix --- gap/semigroups/semicons.gi | 3 +++ tst/standard/semigroups/semicons.tst | 22 ---------------------- 2 files changed, 3 insertions(+), 22 deletions(-) diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 887ec1d45..3cea3db6a 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -418,6 +418,9 @@ function(arg...) elif Length(arg) = 2 then filter := arg[1]; n := arg[2]; + else + ErrorNoReturn("the arguments must be a positive integer or a filter ", + "and a positive integer"); fi; if not IsPosInt(n) or not IsOperation(filter) then diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index f134caf73..71b776f88 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -510,9 +510,6 @@ eger gap> S := FreeSemilattice(IsPartialPermSemigroup, true); Error, the arguments must be a positive integer or a filter and a positive int\ eger -gap> S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 100); - # constructions: FreeSemilattice: known properties and attributes, 17 gap> S := FreeSemilattice(17);; @@ -531,25 +528,6 @@ gap> S := FreeSemilattice(5); gap> S := FreeSemilattice(21); - - The optional argument filt may be one of the following: - - IsTransformationSemigroup - (the default, if filt is not specified), - IsPartialPermSemigroup, - IsFpSemigroup, - IsBipartitionSemigroup, - IsPBRSemigroup, - IsBooleanMatSemigroup, - IsNTPMatrixSemigroup, - IsMaxPlusMatrixSemigroup, - IsMinPlusMatrixSemigroup, - IsTropicalMaxPlusMatrixSemigroup, - IsTropicalMinPlusMatrixSemigroup, - IsProjectiveMaxPlusMatrixSemigroup, - IsIntegerMatrixSemigroup. - - # constructions: FreeSemilattice: transformation semigroup gap> S := FreeSemilattice(IsTransformationSemigroup, 1); From 2e4c7aabc7d4bc1c41a9d93388dd4ebf98683b51 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 14 Feb 2024 14:58:22 +0000 Subject: [PATCH 07/15] Dial back on the number of tests --- tst/standard/semigroups/semicons.tst | 125 --------------------------- 1 file changed, 125 deletions(-) diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index 71b776f88..b9f8d8def 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -538,131 +538,6 @@ gap> S := FreeSemilattice(IsTransformationSemigroup, 5); gap> S := FreeSemilattice(IsTransformationSemigroup, 11); -# constructions: FreeSemilattice: partial perm semigroup -S := FreeSemilattice(IsPartialPermSemigroup, 1); - -S := FreeSemilattice(IsPartialPermSemigroup, 2); - -S := FreeSemilattice(IsPartialPermSemigroup, 5); - -S := FreeSemilattice(IsPartialPermSemigroup, 11); - - -# constructions: FreeSemilattice: bipartition semigroup -S := FreeSemilattice(IsBipartitionSemigroup, 1); - -S := FreeSemilattice(IsBipartitionSemigroup, 2); - -S := FreeSemilattice(IsBipartitionSemigroup, 5); - -S := FreeSemilattice(IsBipartitionSemigroup, 11); - - -# constructions: FreeSemilattice: PBR semigroup -S := FreeSemilattice(IsPBRSemigroup, 1); - -S := FreeSemilattice(IsPBRSemigroup, 2); - -S := FreeSemilattice(IsPBRSemigroup, 5); - -S := FreeSemilattice(IsPBRSemigroup, 11); - -S := FreeSemilattice(IsBooleanMatSemigroup, 1); - -# constructions: FreeSemilattice: Boolean matrix semigroup - -S := FreeSemilattice(IsBooleanMatSemigroup, 2); - -S := FreeSemilattice(IsBooleanMatSemigroup, 5); - -S := FreeSemilattice(IsBooleanMatSemigroup, 11); - - -# constructions: FreeSemilattice: NTP matrix semigroup -S := FreeSemilattice(IsNTPMatrixSemigroup, 1); - -S := FreeSemilattice(IsNTPMatrixSemigroup, 2); - -S := FreeSemilattice(IsNTPMatrixSemigroup, 5); - -S := FreeSemilattice(IsNTPMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: max-plus matrix semigroup -S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 1); - -S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 2); - -S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 5); - -S := FreeSemilattice(IsMaxPlusMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: min-plus matrix semigroup -S := FreeSemilattice(IsMinPlusMatrixSemigroup, 1); - -S := FreeSemilattice(IsMinPlusMatrixSemigroup, 2); - -S := FreeSemilattice(IsMinPlusMatrixSemigroup, 5); - -S := FreeSemilattice(IsMinPlusMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: tropical max-plus matrix semigroup -S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 1); - -S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 2); - -S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 5); - -S := FreeSemilattice(IsTropicalMaxPlusMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: tropical min-plus matrix semigroup -S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 1); - -S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 2); - -S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 5); - -S := FreeSemilattice(IsTropicalMinPlusMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: projective max-plus matrix semigroup -S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 1); - -S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 2); - -S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 5); - -S := FreeSemilattice(IsProjectiveMaxPlusMatrixSemigroup, 11); - - -# constructions: FreeSemilattice: integer matrix semigroup -S := FreeSemilattice(IsIntegerMatrixSemigroup, 1); - -S := FreeSemilattice(IsIntegerMatrixSemigroup, 2); - -S := FreeSemilattice(IsIntegerMatrixSemigroup, 5); - -S := FreeSemilattice(IsIntegerMatrixSemigroup, 11); - - # constructions: ZeroSemigroup: errors gap> S := ZeroSemigroup(0); Error, the arguments must be a positive integer or a filter and a positive int\ From 1cc19e1a64c1eeda2e688c931e0e23799b15d8b1 Mon Sep 17 00:00:00 2001 From: James Mitchell Date: Mon, 11 Mar 2024 15:34:21 +0000 Subject: [PATCH 08/15] Apply suggestions from code review --- doc/semicons.xml | 2 +- gap/semigroups/semicons.gi | 13 +------------ 2 files changed, 2 insertions(+), 13 deletions(-) diff --git a/doc/semicons.xml b/doc/semicons.xml index c1267b7f7..e086145b8 100644 --- a/doc/semicons.xml +++ b/doc/semicons.xml @@ -151,7 +151,7 @@ true]]> - A free semilattice of n generators. + A free semilattice with n generators. If n is a positive integer, then this function returns a free diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 3cea3db6a..6cb295dfb 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -419,8 +419,7 @@ function(arg...) filter := arg[1]; n := arg[2]; else - ErrorNoReturn("the arguments must be a positive integer or a filter ", - "and a positive integer"); + ErrorNoReturn("expected 2 arguments found ", Length(arg)); fi; if not IsPosInt(n) or not IsOperation(filter) then @@ -431,16 +430,6 @@ function(arg...) S := FreeSemilatticeCons(filter, n); SetSize(S, 2 ^ n - 1); - # SetIsRectangularBand(S, true); - # SetNrRClasses(S, m); - # SetNrLClasses(S, n); - # if m <> 1 or n <> 1 then - # SetIsGroupAsSemigroup(S, false); - # SetIsZeroSemigroup(S, false); - # SetIsTrivial(S, false); - # fi; - # SetIsRightZeroSemigroup(S, m = 1); - # SetIsLeftZeroSemigroup(S, n = 1); return S; end); From c9c20625efea6a10c8b2f8d3ffedab35c12a694e Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Tue, 12 Mar 2024 12:36:21 +0000 Subject: [PATCH 09/15] Change tst to reflect the new error msg --- gap/semigroups/semicons.gi | 1 + tst/standard/semigroups/semicons.tst | 3 +-- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 6cb295dfb..746a6aded 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -430,6 +430,7 @@ function(arg...) S := FreeSemilatticeCons(filter, n); SetSize(S, 2 ^ n - 1); + SetIsSemilattice(S, true); return S; end); diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index b9f8d8def..65124c822 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -505,8 +505,7 @@ gap> S := FreeSemilattice(IsPartialPermSemigroup, 0); Error, the arguments must be a positive integer or a filter and a positive int\ eger gap> S := FreeSemilattice(IsPermGroup, 1, 1); -Error, the arguments must be a positive integer or a filter and a positive int\ -eger +Error, expected 2 arguments found 3 gap> S := FreeSemilattice(IsPartialPermSemigroup, true); Error, the arguments must be a positive integer or a filter and a positive int\ eger From a36b83480902fde4fca913a0d15900a65a83cc44 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 13 Mar 2024 15:25:35 +0000 Subject: [PATCH 10/15] Add Monoid constructors to FreeSemilatticeCons --- doc/semicons.xml | 13 +++++ gap/semigroups/semicons.gi | 77 +++++++++++++++++++++++++++- tst/standard/semigroups/semicons.tst | 12 ++--- 3 files changed, 94 insertions(+), 8 deletions(-) diff --git a/doc/semicons.xml b/doc/semicons.xml index e086145b8..df8c0f564 100644 --- a/doc/semicons.xml +++ b/doc/semicons.xml @@ -162,18 +162,31 @@ true]]> IsTransformationSemigroup (the default, if filt is not specified), + IsTransformationMonoid, IsPartialPermSemigroup, + IsPartialPermMonoid, IsFpSemigroup, + IsFpMonoid, IsBipartitionSemigroup, + IsBipartitionMonoid, IsPBRSemigroup, + IsPBRMonoid, IsBooleanMatSemigroup, + IsBooleanMatMonoid, IsNTPMatrixSemigroup, + IsNTPMatrixMonoid, IsMaxPlusMatrixSemigroup, + IsMaxPlusMatrixMonoid, IsMinPlusMatrixSemigroup, + IsMinPlusMatrixMonoid, IsTropicalMaxPlusMatrixSemigroup, + IsTropicalMaxPlusMatrixMonoid, IsTropicalMinPlusMatrixSemigroup, + IsTropicalMinPlusMatrixMonoid, IsProjectiveMaxPlusMatrixSemigroup, + IsProjectiveMaxPlusMatrixMonoid, IsIntegerMatrixSemigroup. + IsIntegerMatrixMonoid. [x * x, x]); + return F / Concatenation(commR, idemR); +end); + InstallMethod(FreeSemilatticeCons, "for IsTransformationSemigroup and a pos int", [IsTransformationSemigroup, IsPosInt], @@ -471,6 +496,20 @@ function(_, n) return Semigroup(gen); end); +InstallMethod(FreeSemilatticeCons, +"for IsTransformationSemigroup and a pos int", +[IsTransformationMonoid, IsPosInt], +function(_, n) + local gen, i, L; + gen := []; + for i in [1 .. n] do + L := [1 .. n + 1]; + L[i] := n + 1; + Add(gen, Transformation(L)); + od; + return Monoid(gen); +end); + InstallMethod(FreeSemilatticeCons, "for IsPartialPermSemigroup and a pos int", [IsPartialPermSemigroup, IsPosInt], @@ -485,6 +524,20 @@ function(_, n) return Semigroup(gen); end); +InstallMethod(FreeSemilatticeCons, +"for IsPartialPermSemigroup and a pos int", +[IsPartialPermMonoid, IsPosInt], +function(_, n) + local gen, i, L; + gen := []; + for i in [1 .. n] do + L := [1 .. n]; + Remove(L, i); + Add(gen, PartialPerm(L, L)); + od; + return Monoid(gen); +end); + # Free semilattice: other constructors for _IsXSemigroup in ["IsBipartitionSemigroup", @@ -505,6 +558,26 @@ for _IsXSemigroup in ["IsBipartitionSemigroup", FreeSemilatticeCons(IsTransformationSemigroup, n)); end); od; + +for _IsXMonoid in ["IsBipartitionMonoid", + "IsPBRMonoid", + "IsBooleanMatMonoid", + "IsNTPMatrixMonoid", + "IsMaxPlusMatrixMonoid", + "IsMinPlusMatrixMonoid", + "IsTropicalMaxPlusMatrixMonoid", + "IsTropicalMinPlusMatrixMonoid", + "IsProjectiveMaxPlusMatrixMonoid", + "IsIntegerMatrixMonoid"] do + InstallMethod(FreeSemilatticeCons, + Concatenation("for ", _IsXMonoid, ", and pos int"), + [ValueGlobal(_IsXMonoid), IsPosInt], + function(filter, n) + return AsMonoid(filter, + FreeSemilatticeCons(IsTransformationMonoid, n)); + end); +od; + Unbind(_IsXSemigroup); # Zero semigroup: main method diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index 65124c822..e66c6316e 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -521,21 +521,21 @@ true gap> S := FreeSemilattice(1); gap> S := FreeSemilattice(2); - + gap> S := FreeSemilattice(5); - + gap> S := FreeSemilattice(21); - + # constructions: FreeSemilattice: transformation semigroup gap> S := FreeSemilattice(IsTransformationSemigroup, 1); gap> S := FreeSemilattice(IsTransformationSemigroup, 2); - + gap> S := FreeSemilattice(IsTransformationSemigroup, 5); - + gap> S := FreeSemilattice(IsTransformationSemigroup, 11); - + # constructions: ZeroSemigroup: errors gap> S := ZeroSemigroup(0); From c583ad60a26cd15a9127d2b2fb6f5f56e2dfc1b3 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 13 Mar 2024 16:35:30 +0000 Subject: [PATCH 11/15] Unbind _IsXMonoid in semicons.gi --- gap/semigroups/semicons.gi | 1 + 1 file changed, 1 insertion(+) diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 97dbd4f68..3689ca2e9 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -579,6 +579,7 @@ for _IsXMonoid in ["IsBipartitionMonoid", od; Unbind(_IsXSemigroup); +Unbind(_IsXMonoid); # Zero semigroup: main method From fa9344fa86f7578e6c1e763dc7fafb01f39b1757 Mon Sep 17 00:00:00 2001 From: Hyeokjun Kwon Date: Wed, 13 Mar 2024 17:10:28 +0000 Subject: [PATCH 12/15] Update semicons.xml and semicons.gi files --- doc/semicons.xml | 7 ++++--- gap/semigroups/semicons.gi | 4 ++-- tst/standard/semigroups/semicons.tst | 3 ++- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/doc/semicons.xml b/doc/semicons.xml index df8c0f564..07f2d8f78 100644 --- a/doc/semicons.xml +++ b/doc/semicons.xml @@ -191,11 +191,12 @@ true]]> S := FreeSemilattice(IsTransformationSemigroup, 5); - + gap> T := FreeSemilattice(IsPartialPermSemigroup, 3); - + gap> U := FreeSemilattice(IsBooleanMatSemigroup, 4); - + ]]> diff --git a/gap/semigroups/semicons.gi b/gap/semigroups/semicons.gi index 3689ca2e9..a9bbddaf2 100644 --- a/gap/semigroups/semicons.gi +++ b/gap/semigroups/semicons.gi @@ -428,14 +428,14 @@ function(arg...) fi; S := FreeSemilatticeCons(filter, n); - + if "IsMagmaWithOne" in NamesFilter(filter) then SetSize(S, 2 ^ n); else SetSize(S, 2 ^ n - 1); fi; - # SetIsSemilattice(S, true); + SetIsSemilattice(S, true); return S; end); diff --git a/tst/standard/semigroups/semicons.tst b/tst/standard/semigroups/semicons.tst index e66c6316e..34986b2d0 100644 --- a/tst/standard/semigroups/semicons.tst +++ b/tst/standard/semigroups/semicons.tst @@ -525,7 +525,8 @@ gap> S := FreeSemilattice(2); gap> S := FreeSemilattice(5); gap> S := FreeSemilattice(21); - + # constructions: FreeSemilattice: transformation semigroup gap> S := FreeSemilattice(IsTransformationSemigroup, 1); From 0a8c8eb0981d3250920866c911442762436df41a Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Wed, 28 Jun 2023 11:24:48 +0200 Subject: [PATCH 13/15] Replace Dot -> Graphviz --- PackageInfo.g | 1 + doc/display.xml | 16 +- etc/code-coverage-test-gap.py | 117 ++ gap/attributes/factor.gd | 5 + gap/attributes/factor.gi | 31 + gap/congruences/congwordgraph.gi | 1 + gap/semigroups/semifp.gi | 23 +- gap/tools/display.gd | 19 +- gap/tools/display.gi | 906 +++++++++++----- tst/standard/semigroups/semifp.tst | 3 +- tst/standard/tools/display.tst | 1581 ++++++++++++---------------- 11 files changed, 1520 insertions(+), 1183 deletions(-) create mode 100755 etc/code-coverage-test-gap.py diff --git a/PackageInfo.g b/PackageInfo.g index 26effbfe5..448766d7d 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -379,6 +379,7 @@ Dependencies := rec( NeededOtherPackages := [["datastructures", ">=0.2.5"], ["digraphs", ">=1.6.2"], ["genss", ">=1.6.5"], + ["graphviz", ">=0.0.0"], ["images", ">=1.3.1"], ["IO", ">=4.5.1"], ["orb", ">=4.8.2"]], diff --git a/doc/display.xml b/doc/display.xml index eaaa8e8d2..42405b422 100644 --- a/doc/display.xml +++ b/doc/display.xml @@ -265,13 +265,15 @@ gap> FileString("t3.dot", DotString(S)); gap> S := DualSymmetricInverseMonoid(4); gap> DotSemilatticeOfIdempotents(S); -"//dot\ngraph graphname {\n node [shape=point]\nranksep=2;\nsubgraph \ -cluster_1{\n15 \n}\nsubgraph cluster_2{\n5 11 14 12 13 8 \n}\nsubgraph\ - cluster_3{\n2 10 6 3 4 9 7 \n}\nsubgraph cluster_4{\n1 \n}\n2 -- 1\n3\ - -- 1\n4 -- 1\n5 -- 2\n5 -- 3\n5 -- 4\n6 -- 1\n7 -- 1\n8 -- 2\n8 -- 6\ -\n8 -- 7\n9 -- 1\n10 -- 1\n11 -- 2\n11 -- 9\n11 -- 10\n12 -- 3\n12 -- \ -6\n12 -- 9\n13 -- 3\n13 -- 7\n13 -- 10\n14 -- 4\n14 -- 6\n14 -- 10\n15\ - -- 5\n15 -- 8\n15 -- 11\n15 -- 12\n15 -- 13\n15 -- 14\n }"]]> +"//dot\ngraph semilattice {\n\tnode[shape=point] ranksep=2 \nsubgraph \ +cluster_1 {\n\t15\n}\nsubgraph cluster_2 {\n\t5\n\t11\n\t14\n\t12\n\t1\ +3\n\t8\n}\nsubgraph cluster_3 {\n\t2\n\t10\n\t6\n\t3\n\t4\n\t9\n\t7\n}\ +\nsubgraph cluster_4 {\n\t1\n}\n\t2 -- 1\n\t3 -- 1\n\t4 -- 1\n\t5 -- 2\ +\n\t5 -- 3\n\t5 -- 4\n\t6 -- 1\n\t7 -- 1\n\t8 -- 2\n\t8 -- 6\n\t8 -- 7\ +\n\t9 -- 1\n\t10 -- 1\n\t11 -- 2\n\t11 -- 9\n\t11 -- 10\n\t12 -- 3\n\t\ +12 -- 6\n\t12 -- 9\n\t13 -- 3\n\t13 -- 7\n\t13 -- 10\n\t14 -- 4\n\t14 \ +-- 6\n\t14 -- 10\n\t15 -- 5\n\t15 -- 8\n\t15 -- 11\n\t15 -- 12\n\t15 -\ +- 13\n\t15 -- 14\n}\n"]]> <#/GAPDoc> diff --git a/etc/code-coverage-test-gap.py b/etc/code-coverage-test-gap.py new file mode 100755 index 000000000..7c30416ac --- /dev/null +++ b/etc/code-coverage-test-gap.py @@ -0,0 +1,117 @@ +#!/usr/bin/env python3 +""" +""" + +import argparse, tempfile, subprocess, re, sys, os, webbrowser +from os.path import exists, isdir, isfile + +_ERR_PREFIX = "\033[31mcode-coverage-test-gap.py: error: " +_INFO_PREFIX = "\033[40;38;5;82m" + +_PARSER = argparse.ArgumentParser( + prog="code-coverage-test-gap.py", usage="%(prog)s [options]" +) +_PARSER.add_argument( + "tstfiles", + nargs="+", + type=str, + help="the test files you want to check code coverage for" + + "(must be at least one)", +) +_PARSER.add_argument( + "--gap-root", + nargs="?", + type=str, + help="the gap root directory (default: ~/gap)", + default="~/gap/", +) +_PARSER.add_argument( + "--open", + nargs="?", + type=str, + help=("open the html page for this file " + "(default: None)"), + default=None, +) + +_ARGS = _PARSER.parse_args() +if not _ARGS.gap_root[-1] == "/": + _ARGS.gap_root += "/" + +if exists("gap") and isdir("gap"): + _PROFILE_DIR = "/gap/" +elif exists("lib") and isdir("lib"): + _PROFILE_DIR = "/lib/" +else: + sys.exit(_ERR_PREFIX + "no directory gap or lib to profile!\033[0m") + +_ARGS.gap_root = os.path.expanduser(_ARGS.gap_root) +if not (exists(_ARGS.gap_root) and isdir(_ARGS.gap_root)): + sys.exit(_ERR_PREFIX + "can't find GAP root directory!\033[0m") + +for f in _ARGS.tstfiles: + if not (exists(f) and isfile(f)): + sys.exit(_ERR_PREFIX + f + " does not exist!\033[0m") + +_DIR = tempfile.mkdtemp() +print(f"{_INFO_PREFIX}Using temporary directory: {_DIR}\033[0m") + +_COMMANDS = 'echo "' +for f in _ARGS.tstfiles: + _COMMANDS += f'Test(\\"{f}\\");;\n' +_COMMANDS += ( + '''UncoverageLineByLine();; +LoadPackage(\\"profiling\\", false);; +filesdir := \\"''' + + os.getcwd() + + _PROFILE_DIR + + """\\";;\n""" +) +_COMMANDS += 'outdir := \\"' + _DIR + '\\";;\n' +_COMMANDS += 'x := ReadLineByLineProfile(\\"' + _DIR + '/profile.gz\\");;\n' +_COMMANDS += 'OutputAnnotatedCodeCoverageFiles(x, filesdir, outdir);"' + +pro1 = subprocess.Popen(_COMMANDS, stdout=subprocess.PIPE, shell=True) +_RUN_GAP = _ARGS.gap_root + "gap -A -m 1g -T --cover " + _DIR + "/profile.gz" + +try: + pro2 = subprocess.Popen(_RUN_GAP, stdin=pro1.stdout, shell=True) + pro2.wait() +except KeyboardInterrupt: + pro1.terminate() + pro1.wait() + pro2.terminate() + pro2.wait() + sys.exit("\033[31mKilled!\033[0m") +except (subprocess.CalledProcessError, IOError, OSError): + sys.exit(_ERR_PREFIX + "Something went wrong calling GAP!\033[0m") + +suffix = "" +if _ARGS.open: + filename = ( + _DIR + + "/" + + os.getcwd().replace("/", "_") + + "_" + + _ARGS.open.replace("/", "_") + + ".html" + ) + p = re.compile(r"") + with open(filename, "r") as f: + m = p.search(f.read()) + if m: + suffix += f"#line{m.group(1)}" +else: + filename = _DIR + "/index.html" + +if exists(filename) and isfile(filename): + if _ARGS.open: + filename += suffix + try: + webbrowser.get("safari").open(f"file://{filename}", new=2) + except Exception: + webbrowser.open(f"file://{filename}", new=2) +else: + sys.exit(f"\n{_ERR_PREFIX}Failed to open file://{filename}\033[0m") + +print(f"\n{_INFO_PREFIX}SUCCESS!\033[0m") +sys.exit(0) diff --git a/gap/attributes/factor.gd b/gap/attributes/factor.gd index 91add8019..99c97ef1f 100644 --- a/gap/attributes/factor.gd +++ b/gap/attributes/factor.gd @@ -15,3 +15,8 @@ DeclareOperation("NonTrivialFactorization", DeclareOperation("Factorization", [IsLambdaOrb, IsPosInt, IsPerm]); DeclareOperation("Factorization", [IsSemigroup, IsMultiplicativeElement]); DeclareOperation("TraceSchreierTreeForward", [IsSemigroupData, IsPosInt]); + +DeclareOperation("MonoidFactorization", + [IsMonoid, IsMultiplicativeElementWithOne]); +DeclareOperation("MinimalMonoidFactorization", + [IsMonoid, IsMultiplicativeElementWithOne]); diff --git a/gap/attributes/factor.gi b/gap/attributes/factor.gi index 21021ca37..b20729a12 100644 --- a/gap/attributes/factor.gi +++ b/gap/attributes/factor.gi @@ -451,3 +451,34 @@ function(S, x) return word1; end); + +SEMIGROUPS._MonoidFactorization := function(M, word) + local pos, i; + + pos := Position(GeneratorsOfSemigroup(M), One(M)); + if pos = fail then + return word; + fi; + # Words are in terms of GeneratorsOfSemigroup(S) but we want it in terms of + # GeneratorsOfMonoid(S), so we have to normalise + i := 1; + while i <= Length(word) do + if word[i] = pos then + Remove(word, i); + else + if word[i] > pos then + word[i] := word[i] - 1; + fi; + i := i + 1; + fi; + od; + return word; +end; + +InstallMethod(MonoidFactorization, "for a monoid and element-with-one", +[IsMonoid, IsMultiplicativeElementWithOne], +{M, x} -> SEMIGROUPS._MonoidFactorization(M, Factorization(M, x))); + +InstallMethod(MinimalMonoidFactorization, "for a monoid and element-with-one", +[IsMonoid, IsMultiplicativeElementWithOne], +{M, x} -> SEMIGROUPS._MonoidFactorization(M, MinimalFactorization(M, x))); diff --git a/gap/congruences/congwordgraph.gi b/gap/congruences/congwordgraph.gi index b200a3368..2c0161ff9 100644 --- a/gap/congruences/congwordgraph.gi +++ b/gap/congruences/congwordgraph.gi @@ -10,6 +10,7 @@ ## This file contains implementation for left, right, and two-sided ## congruences that are defined in terms of a IsWordGraph. +# TODO promote this to a proper operation BindGlobal("_MonoidFactorization", function(M, x) local word, pos, i; diff --git a/gap/semigroups/semifp.gi b/gap/semigroups/semifp.gi index 2b0d77396..bfc19d691 100644 --- a/gap/semigroups/semifp.gi +++ b/gap/semigroups/semifp.gi @@ -957,16 +957,27 @@ SEMIGROUPS.WordToExtRepObj := function(word) return ext_rep_obj; end; -SEMIGROUPS.ExtRepObjToString := function(ext_rep_obj) - local alphabet, out, i; - alphabet := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; +SEMIGROUPS.ExtRepObjToString := function(arg...) + local ext_rep_obj, names, out, i; + + if Length(arg) = 1 then + ext_rep_obj := arg[1]; + names := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + elif Length(arg) = 2 then + ext_rep_obj := arg[1]; + names := Concatenation(arg[2]); + else + ErrorNoReturn("expected 1 or 2 arguments, found ", Length(arg)); + fi; + out := ""; for i in [1, 3 .. Length(ext_rep_obj) - 1] do - if ext_rep_obj[i] > Length(alphabet) then + if ext_rep_obj[i] > Length(names) then ErrorNoReturn("the maximum value in an odd position of the ", - "argument must be at most ", Length(alphabet)); + "argument must be at most ", Length(names), " found ", + ext_rep_obj[i]); fi; - Add(out, alphabet[ext_rep_obj[i]]); + Add(out, names[ext_rep_obj[i]]); if ext_rep_obj[i + 1] > 1 then Append(out, " ^ "); Append(out, String(ext_rep_obj[i + 1])); diff --git a/gap/tools/display.gd b/gap/tools/display.gd index f0a16f31c..40d0c36f3 100644 --- a/gap/tools/display.gd +++ b/gap/tools/display.gd @@ -1,7 +1,7 @@ ############################################################################# ## ## tools/display.gd -## Copyright (C) 2013-2022 James D. Mitchell +## Copyright (C) 2013-2024 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## @@ -18,7 +18,24 @@ DeclareOperation("TexString", [IsObject, IsObject]); DeclareOperation("TikzLeftCayleyDigraph", [IsSemigroup]); DeclareOperation("TikzRightCayleyDigraph", [IsSemigroup]); +DeclareOperation("GraphvizDClasses", [IsSemigroup, IsRecord]); +DeclareOperation("GraphvizDClasses", [IsSemigroup]); + +DeclareOperation("GraphvizLeftCayleyDigraph", [IsSemigroup, IsHomogeneousList]); +DeclareOperation("GraphvizLeftCayleyDigraph", [IsSemigroup]); +DeclareOperation("GraphvizRightCayleyDigraph", [IsSemigroup, IsHomogeneousList]); +DeclareOperation("GraphvizRightCayleyDigraph", [IsSemigroup]); +DeclareOperation("DotLeftCayleyDigraph", [IsSemigroup, IsHomogeneousList]); DeclareOperation("DotLeftCayleyDigraph", [IsSemigroup]); +DeclareOperation("DotRightCayleyDigraph", [IsSemigroup, IsHomogeneousList]); DeclareOperation("DotRightCayleyDigraph", [IsSemigroup]); +# TODO homogeneous list? +DeclareOperation("GraphvizWordGraph", [IsDigraph]); +DeclareOperation("GraphvizWordGraph", [IsDigraph, IsList, IsList]); + +DeclareOperation("DotWordGraph", [IsDigraph]); +DeclareOperation("DotWordGraph", [IsDigraph, IsList, IsList]); + +DeclareAttribute("GraphvizSemilatticeOfIdempotents", IsInverseSemigroup); DeclareAttribute("DotSemilatticeOfIdempotents", IsInverseSemigroup); diff --git a/gap/tools/display.gi b/gap/tools/display.gi index a17aa5b3d..9a8b31e1a 100644 --- a/gap/tools/display.gi +++ b/gap/tools/display.gi @@ -1,29 +1,64 @@ ############################################################################# ## ## tools/display.gi -## Copyright (C) 2013-2022 James D. Mitchell +## Copyright (C) 2013-2024 James D. Mitchell ## ## Licensing information can be found in the README file of this package. ## ############################################################################# ## +############################################################################# +# Tex strings +############################################################################# + +InstallMethod(TexString, "for a transformation and a pos int", +[IsTransformation, IsPosInt], +function(f, deg) + local str; + + if deg < DegreeOfTransformation(f) then + ErrorNoReturn("the 2nd argument (a pos. int.) is less than ", + "the degree of the 1st argument (a ", + "transformation)"); + fi; + str := "\\begin{pmatrix}\n "; + Append(str, JoinStringsWithSeparator(List([1 .. deg], String), " & ")); + Append(str, " \\\\\n "); + Append(str, JoinStringsWithSeparator(List([1 .. deg], + i -> String(i ^ f)), " & ")); + Append(str, "\n\\end{pmatrix}"); + return str; +end); + +InstallMethod(TexString, "for a transformation", +[IsTransformation], +f -> TexString(f, DegreeOfTransformation(f))); + +InstallMethod(TexString, "for a transformation collection", +[IsTransformationCollection], +function(coll) + local deg; + deg := DegreeOfTransformationCollection(coll); + return JoinStringsWithSeparator(List(coll, x -> TexString(x, deg)), "\n"); +end); + +############################################################################# +# Tikz internal stuff ############################################################################# SEMIGROUPS.GetTikzInit := function(opts) - local extra; + local extra, strings; + if IsBound(opts.extraInit) then extra := opts.extraInit; else extra := ""; fi; - return StringFormatted("1\n2\n3\n4\n5\n", - "%latex", - "\\documentclass{minimal}", - "\\usepackage{tikz}", - extra, - "\\begin{document}"); + strings := ["%latex", "\\documentclass{minimal}", "\\usepackage{tikz}", + extra, "\\begin{document}"]; + return JoinStringsWithSeparator(strings, "\n"); end; SEMIGROUPS.TikzEnd := "\\end{document}"; @@ -68,6 +103,8 @@ SEMIGROUPS.TikzBlocksOpts := rec(labels := "above", colors := false); ############################################################################### +# Tikz collections +############################################################################### InstallMethod(TikzString, "for a collection and record", [IsCollection, IsRecord], @@ -90,6 +127,8 @@ function(coll, opts) return str; end); +############################################################################# +# Tikz pbrs ############################################################################# InstallMethod(TikzString, "for a pbr collection", @@ -249,6 +288,8 @@ function(x, opts) return str; end); +############################################################################# +# Tikz bipartitions ############################################################################# InstallMethod(TikzString, "for a bipartition collection", @@ -400,350 +441,661 @@ function(x, opts) return str; end); +############################################################################# +# Tikz Cayley graphs +############################################################################# + +InstallMethod(TikzLeftCayleyDigraph, "for a semigroup", [IsSemigroup], +S -> TikzString(LeftCayleyDigraph(S))); + +InstallMethod(TikzRightCayleyDigraph, "for a semigroup", [IsSemigroup], +S -> TikzString(RightCayleyDigraph(S))); + +InstallMethod(TikzString, "for a Cayley digraph", [IsCayleyDigraph], +function(digraph) + local S, vertex, edge, str, nbs, x, from, gen; + + S := SemigroupOfCayleyDigraph(digraph); + if not CanUseFroidurePin(S) or Size(S) > 26 then + TryNextMethod(); + fi; + + vertex := function(x) + local word, name, label; + word := MinimalFactorization(S, x); + name := SEMIGROUPS.WordToString(word); + label := SEMIGROUPS.ExtRepObjToString(SEMIGROUPS.WordToExtRepObj(word)); + return Concatenation(" \\node [vertex] (", name, ") at (0, 0) {};\n", + " \\node at (0, 0) {$", label, "$};\n\n"); + end; + + edge := function(from, to, gen) + local word; + word := MinimalFactorization(S, AsListCanonical(S)[from]); + from := SEMIGROUPS.WordToString(word); + word := MinimalFactorization(S, AsListCanonical(S)[to]); + to := SEMIGROUPS.WordToString(word); + gen := SEMIGROUPS.WordToString([gen]); + if from <> to then + return Concatenation(" \\path[->] (", from, + ") edge [edge] node {$", gen, "$} (", + to, ");\n"); + else + return Concatenation(" \\path[->] (", from, + ") edge [loop]\n", + " node {$", gen, "$} (", to, ");\n"); + fi; + end; + + str := ""; + + Append(str, "\\begin{tikzpicture}[scale=1, auto, \n"); + Append(str, " vertex/.style={circle, draw, thick, fill=white, minimum"); + Append(str, " size=0.65cm},\n"); + Append(str, " edge/.style={arrows={-angle 90}, thick},\n"); + Append(str, " loop/.style={min distance=5mm,looseness=5,"); + Append(str, "arrows={-angle 90},thick}]\n\n"); + + Append(str, " % Vertices . . .\n"); + for x in AsListCanonical(S) do + Append(str, vertex(x)); + od; + + Append(str, " % Edges . . .\n"); + nbs := OutNeighbours(digraph); + for from in [1 .. Size(S)] do + for gen in [1 .. Size(nbs[from])] do + Append(str, edge(from, nbs[from][gen], gen)); + od; + od; + + Append(str, "\\end{tikzpicture}"); + return str; +end); + +############################################################################# +# Dot for semigroups/monoids ############################################################################# InstallMethod(DotString, "for a semigroup", [IsSemigroup], -S -> DotString(S, rec())); +S -> AsString(GraphvizDClasses(S))); + +InstallMethod(DotString, "for a semigroup", [IsSemigroup, IsRecord], +{S, opts} -> AsString(GraphvizDClasses(S, opts))); + +InstallMethod(GraphvizDClasses, "for a semigroup", [IsSemigroup], +S -> GraphvizDClasses(S, rec())); + +SEMIGROUPS.HTMLTableOfDClass := function(D, n, R, struct, number) + local mat, str, next, item, bgcolor, color, c, r; + + Assert(0, IsGreensDClass(D)); + + mat := Matrix(R); + + str := "<\n"); + + str := StringFormatted(str, n); + + if number then + next := ""; + Append(str, StringFormatted(next, NrRClasses(D), n)); + fi; + + for c in Columns(R) do + Append(str, ""); + for r in Rows(R) do + next := ""; + item := "*"; + if mat[c][r] <> 0 then + bgcolor := "gray"; + item := struct; + color := "black"; + else + bgcolor := "white"; + color := "white"; + fi; + Append(str, StringFormatted(next, bgcolor, color, item)); + od; + Append(str, "\n"); + od; + Append(str, "
{}
{}
>"); + return str; +end; -InstallMethod(DotString, "for a semigroup and record", +InstallMethod(GraphvizDClasses, "for a semigroup and record", [IsSemigroup, IsRecord], function(S, opts) - local es, elts, str, i, color, pos, gp, iso, inv, RMS, mat, G, x, D, rel, ii, - di, j, dk, k, d, l, col, row; + local HTML, gv, i, ZeroMat, injection, RMS, sd, n, label, D, rel, j; - # process the options - if not IsBound(opts.maximal) then + # Process the options + if not IsBound(opts.maximal) or not opts.maximal in [true, false] then opts.maximal := false; fi; - if not IsBound(opts.number) then + if not IsBound(opts.number) or not opts.number in [true, false] then opts.number := true; fi; - if not IsBound(opts.normal) then + if not IsBound(opts.normal) or not opts.number in [true, false] then opts.normal := true; fi; - if not IsBound(opts.highlight) then - opts.highlight := false; # JDM means highlight H-classes - else - for x in opts.highlight do - if not IsBound(x.HighlightGroupHClassColor) then - x.HighlightGroupHClassColor := "#880000"; - fi; - if not IsBound(x.HighlightNonGroupHClassColor) then - x.HighlightNonGroupHClassColor := "#FF0000"; - fi; - od; - fi; + HTML := SEMIGROUPS.HTMLTableOfDClass; - if not IsBound(opts.idempotentsemilattice) then - opts.idempotentsemilattice := false; - elif opts.idempotentsemilattice then - es := IdempotentGeneratedSubsemigroup(S); - elts := Elements(es); # JDM could be enumerator sorted - fi; + gv := GraphvizDigraph("DClasses"); + GraphvizSetAttr(gv, "node [shape=plaintext]"); + GraphvizSetAttr(gv, "edge [color=black, arrowhead=none]"); - str := "//dot\n"; - Append(str, "digraph DClasses {\n"); - Append(str, "node [shape=plaintext]\n"); - Append(str, "edge [color=black,arrowhead=none]\n"); i := 0; - for d in DClasses(S) do + ZeroMat := {rows, cols} -> List([1 .. rows], r -> [1 .. cols] * 0); - i := i + 1; - Append(str, String(i)); - Append(str, " [shape=box style=invisible "); - Append(str, "label=<\n\n")); - - if opts.number then - Append(str, ""); - fi; - - if not IsRegularDClass(d) then - for l in LClasses(d) do - Append(str, ""); - for x in HClasses(l) do - color := "white"; - if opts.highlight <> false then - pos := PositionProperty(opts.highlight, - record -> x in record.HClasses); - if pos <> fail then - color := opts.highlight[pos].HighlightNonGroupHClassColor; - fi; - fi; - Append(str, Concatenation("")); - od; - Append(str, "\n"); - od; - Append(str, "
"); - Append(str, String(i)); - Append(str, "
*
>];\n"); - continue; - fi; - - if opts.maximal then - gp := StructureDescription(GroupHClass(d)); + if opts.normal then + injection := InjectionNormalizedPrincipalFactor; + else + injection := InjectionPrincipalFactor; + fi; + RMS := function(D) + if IsRegularDClass(D) then + return Range(injection(D)); + else + return ReesZeroMatrixSemigroup(Group(()), + ZeroMat(NrLClasses(D), NrRClasses(D))); fi; + end; - if opts.normal then - iso := InjectionNormalizedPrincipalFactor(d); + for D in DClasses(S) do + i := i + 1; + if opts.maximal and IsRegularDClass(D) then + sd := StructureDescription(GroupHClass(D)); else - iso := InjectionPrincipalFactor(d); + sd := "*"; fi; - inv := InverseGeneralMapping(iso); - RMS := Range(iso); - mat := Matrix(RMS); - G := UnderlyingSemigroup(RMS); - - for col in Columns(RMS) do # Columns of RMS = RClasses - Append(str, ""); - for row in Rows(RMS) do # Rows of RMS = LClasses - Append(str, " false then - x := HClass(d, RMSElement(RMS, row, Identity(G), col) ^ inv); - pos := PositionProperty(opts.highlight, rcd -> x in rcd.HClasses); - fi; - if mat[col][row] <> 0 then - # group H-class - if opts.highlight <> false and pos <> fail then - color := opts.highlight[pos].HighlightGroupHClassColor; - else - color := "gray"; - fi; - Append(str, color); - Append(str, "\""); - if opts.maximal then - Append(str, ">"); - Append(str, gp); - else - if opts.idempotentsemilattice then - x := HClass(d, RMSElement(RMS, row, Identity(G), col) ^ inv); - Append(str, " PORT=\"e"); - Append(str, String(Position(elts, Idempotents(x)[1]))); - Append(str, "\""); - fi; - Append(str, ">*"); - fi; - else - # non-group H-class - if opts.highlight <> false and pos <> fail then - color := opts.highlight[pos].HighlightNonGroupHClassColor; - else - color := "white"; - fi; - Append(str, color); - Append(str, "\">"); - fi; - Append(str, ""); - od; - Append(str, "\n"); - od; - Append(str, ">];\n"); + n := GraphvizAddNode(gv, i); + GraphvizSetAttr(n, "shape", "box"); + GraphvizSetAttr(n, "style", "invisible"); + label := HTML(D, i, RMS(D), sd, opts.number); + GraphvizSetAttr(n, "label", label); od; + D := PartialOrderOfDClasses(S); rel := OutNeighbours(DigraphReflexiveTransitiveReduction(D)); for i in [1 .. Length(rel)] do - ii := String(i); - for k in rel[i] do - Append(str, Concatenation(ii, " -> ", String(k), "\n")); + for j in rel[i] do + GraphvizAddEdge(gv, i, j); od; od; - # add semilattice of idempotents - if opts.idempotentsemilattice then - Append(str, "edge [color=blue,arrowhead=none,style=dashed]\n"); - rel := NaturalPartialOrder(es); - - for i in [1 .. Length(rel)] do - di := String(Position(DClasses(S), DClass(S, elts[i]))); - j := Difference(rel[i], Union(rel{rel[i]})); - i := String(i); - for k in j do - dk := String(Position(DClasses(S), DClass(S, elts[k]))); - k := String(k); - Append(str, Concatenation(di, ":e", i, " -> ", dk, ":e", k, "\n")); - od; - od; - fi; - Append(str, " }"); - - return str; + return gv; end); -InstallMethod(DotSemilatticeOfIdempotents, +InstallMethod(GraphvizSemilatticeOfIdempotents, "for inverse semigroup with inverse op", [IsInverseSemigroup and IsGeneratorsOfInverseSemigroup], function(S) - local U, rel, elts, str, nr, V, j, i, k, D, v; + local E, U, gv, nr, V, cluster, D, v, u; - U := IdempotentGeneratedSubsemigroup(S); - rel := NaturalPartialOrder(U); - elts := Elements(U); + E := IdempotentGeneratedSubsemigroup(S); + U := Elements(E); - str := "//dot\n"; + gv := GraphvizGraph("semilattice"); - Append(str, "graph graphname {\n node [shape=point]\n"); - Append(str, "ranksep=2;\n"); + GraphvizSetAttr(gv, "node[shape=point]"); + GraphvizSetAttr(gv, "ranksep", "2"); nr := 0; for D in GreensDClasses(S) do nr := nr + 1; - V := List(Idempotents(D), x -> String(Position(elts, x))); - Append(str, Concatenation("subgraph cluster_", String(nr), "{\n")); + V := List(Idempotents(D), x -> Position(U, x)); + cluster := GraphvizAddSubgraph(gv, StringFormatted("cluster_{}", nr)); for v in V do - Append(str, v); - Append(str, " "); + GraphvizAddNode(cluster, v); od; - Append(str, "\n"); - Append(str, "}\n"); od; - for i in [1 .. Length(rel)] do - j := Difference(rel[i], Union(rel{rel[i]})); - i := String(i); - for k in j do - k := String(k); - Append(str, Concatenation(i, " -- ", k, "\n")); + D := DigraphNC(IsMutable, NaturalPartialOrder(E)); + DigraphReflexiveTransitiveReduction(D); + + for u in DigraphVertices(D) do + for v in OutNeighboursOfVertexNC(D, u) do + GraphvizAddEdge(gv, u, v); od; od; - Append(str, " }"); - - return str; + return gv; end); -InstallMethod(TexString, "for a transformation and a pos int", -[IsTransformation, IsPosInt], -function(f, deg) - local str, i; +InstallMethod(DotSemilatticeOfIdempotents, +"for inverse semigroup with inverse op", +[IsInverseSemigroup and IsGeneratorsOfInverseSemigroup], +S -> AsString(GraphvizSemilatticeOfIdempotents(S))); - if deg < DegreeOfTransformation(f) then - ErrorNoReturn("the 2nd argument (a pos. int.) is less than ", - "the degree of the 1st argument (a ", - "transformation)"); +######################################################################## +# DotLeft/RightCayleyDigraph +######################################################################## + +InstallMethod(DotLeftCayleyDigraph, "for a semigroup", [IsSemigroup], +S -> AsString(GraphvizLeftCayleyDigraph(S))); + +InstallMethod(DotRightCayleyDigraph, "for a semigroup", [IsSemigroup], +S -> AsString(GraphvizRightCayleyDigraph(S))); + +InstallMethod(DotLeftCayleyDigraph, +"for a semigroup and list of generator names", +[IsSemigroup, IsHomogeneousList], +{S, names} -> AsString(GraphvizLeftCayleyDigraph(S, names))); + +InstallMethod(DotRightCayleyDigraph, +"for a semigroup and list of generator names", +[IsSemigroup, IsHomogeneousList], +{S, names} -> AsString(GraphvizRightCayleyDigraph(S, names))); + +######################################################################## +# GraphvizLeftCayleyDigraph +######################################################################## + +InstallMethod(GraphvizLeftCayleyDigraph, +"for a semigroup and list of generator names", +[IsSemigroup and CanUseFroidurePin, IsHomogeneousList], +function(S, names) + local pos, ToExtRepObj, ToString, label; + + if Length(GeneratorsOfSemigroup(S)) <> Length(names) then + ErrorNoReturn("the 2nd argument (list of names) must have ", + "length equal to Length(GeneratorsOfSemigroup(S)) = ", + Length(GeneratorsOfSemigroup(S)), + "where S is the 1st argument (a semigroup)", + ", but found ", Length(names)); + elif not IsString(names[1]) then + ErrorNoReturn("the 2nd argument (list of names) must consist of ", + "strings, but found ", TNAM_OBJ(names[1])); fi; - str := "\\begin{pmatrix}\n "; - for i in [1 .. deg] do - Append(str, String(i)); - if i <> deg then - Append(str, " & "); - fi; - od; - Append(str, " \\\\\n "); - for i in [1 .. deg] do - Append(str, String(i ^ f)); - if i <> deg then - Append(str, " & "); + + if IsMonoidAsSemigroup(S) then + S := AsMonoid(S); + pos := Position(GeneratorsOfSemigroup(S), One(S)); + if pos <> fail then + names := ShallowCopy(names); + Remove(names, pos); fi; - od; - Append(str, "\n\\end{pmatrix}"); - return str; + return GraphvizLeftCayleyDigraph(S, names); + fi; + ToExtRepObj := SEMIGROUPS.WordToExtRepObj; + ToString := x -> SEMIGROUPS.ExtRepObjToString(x, names); + label := x -> ToString(ToExtRepObj(MinimalFactorization(S, x))); + return GraphvizWordGraph(LeftCayleyDigraph(S), + List(S, label), + List(GeneratorsOfSemigroup(S), label)); end); -InstallMethod(TexString, "for a transformation", -[IsTransformation], -f -> TexString(f, DegreeOfTransformation(f))); +InstallMethod(GraphvizLeftCayleyDigraph, "for a monoid", +[IsMonoid and CanUseFroidurePin, IsHomogeneousList], +function(S, names) + local label, pos, D, x; + + if Length(GeneratorsOfMonoid(S)) <> Length(names) then + ErrorNoReturn("the 2nd argument (list of names) must have ", + "length equal to Length(GeneratorsOfMonoid(S)) = ", + Length(GeneratorsOfMonoid(S)), + "where S is the 1st argument (a monoid)", + ", but found ", Length(names)); + elif not IsString(names[1]) then + ErrorNoReturn("the 2nd argument (list of names) must consist of ", + "strings, but found ", TNAM_OBJ(names[1])); + fi; -InstallMethod(TexString, "for a transformation collection", -[IsTransformationCollection], -function(coll) - local deg; - deg := DegreeOfTransformationCollection(coll); - return JoinStringsWithSeparator(List(coll, x -> TexString(x, deg)), "\n"); + Info(InfoWarning, + 1, + "GraphvizLeftCayleyDigraph: using GeneratorsOfMonoid ", + "instead of GeneratorsOfSemigroup"); + + label := SEMIGROUPS.HTMLSemigroupElement(S, names); + + # TODO replace with LeftCayleyDigraph(S, SomeElements) method instead + pos := Position(GeneratorsOfSemigroup(S), One(S)); + D := LeftCayleyDigraph(S); + if pos <> fail then + D := DigraphMutableCopy(D); + for x in OutNeighbours(D) do + Remove(x, pos); + od; + MakeImmutable(D); + fi; + return GraphvizWordGraph(D, + List(S, label), + List(GeneratorsOfMonoid(S), label)); end); -InstallMethod(TikzLeftCayleyDigraph, "for a semigroup", [IsSemigroup], -S -> TikzString(LeftCayleyDigraph(S))); +InstallMethod(GraphvizLeftCayleyDigraph, "for a semigroup", [IsSemigroup], +function(S) + local names; -InstallMethod(TikzRightCayleyDigraph, "for a semigroup", [IsSemigroup], -S -> TikzString(RightCayleyDigraph(S))); + names := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + names := List([1 .. Size(GeneratorsOfSemigroup(S))], x -> [names[x]]); -InstallMethod(TikzString, "for a Cayley digraph", [IsCayleyDigraph], -function(digraph) - local S, vertex, edge, str, nbs, x, from, gen; + Info(InfoWarning, 1, "GraphvizLeftCayleyDigraph: no generator labels ", + "specified, using ", names, " for GeneratorsOfSemigroup"); - S := SemigroupOfCayleyDigraph(digraph); - if not CanUseFroidurePin(S) or Size(S) > 26 then - TryNextMethod(); - fi; + return GraphvizLeftCayleyDigraph(S, names); +end); - vertex := function(x) - local word, name, label; - word := MinimalFactorization(S, x); - name := SEMIGROUPS.WordToString(word); - label := SEMIGROUPS.ExtRepObjToString(SEMIGROUPS.WordToExtRepObj(word)); - return Concatenation(" \\node [vertex] (", name, ") at (0, 0) {};\n", - " \\node at (0, 0) {$", label, "$};\n\n"); - end; +# The next method doesn't really need to exist but the info warnings make more +# sense with it. +InstallMethod(GraphvizLeftCayleyDigraph, "for a monoid", [IsMonoid], +function(S) + local names; - edge := function(from, to, gen) - local word; - word := MinimalFactorization(S, AsListCanonical(S)[from]); - from := SEMIGROUPS.WordToString(word); - word := MinimalFactorization(S, AsListCanonical(S)[to]); - to := SEMIGROUPS.WordToString(word); - gen := SEMIGROUPS.WordToString([gen]); - if from <> to then - return Concatenation(" \\path[->] (", from, - ") edge [edge] node {$", gen, "$} (", - to, ");\n"); - else - return Concatenation(" \\path[->] (", from, - ") edge [loop]\n", - " node {$", gen, "$} (", to, ");\n"); - fi; - end; + names := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + names := List([1 .. Size(GeneratorsOfMonoid(S))], x -> [names[x]]); - str := ""; + Info(InfoWarning, 1, "GraphvizLeftCayleyDigraph: no generator labels ", + "specified, using ", names, " for GeneratorsOfMonoid"); - Append(str, "\\begin{tikzpicture}[scale=1, auto, \n"); - Append(str, " vertex/.style={circle, draw, thick, fill=white, minimum"); - Append(str, " size=0.65cm},\n"); - Append(str, " edge/.style={arrows={-angle 90}, thick},\n"); - Append(str, " loop/.style={min distance=5mm,looseness=5,"); - Append(str, "arrows={-angle 90},thick}]\n\n"); + return GraphvizLeftCayleyDigraph(S, names); +end); - Append(str, " % Vertices . . .\n"); - for x in AsListCanonical(S) do - Append(str, vertex(x)); +# This method exists so that we use the same letters as S in the output. +InstallMethod(GraphvizLeftCayleyDigraph, "for an fp semigroup", [IsFpSemigroup], +function(S) + local label; + + label := x -> ReplacedString(String(x), "*", ""); + return GraphvizWordGraph(LeftCayleyDigraph(S), + List(S, label), + List(GeneratorsOfSemigroup(S), label)); +end); + +SEMIGROUPS.HTMLSemigroupElement := function(S, names) + if IsFpMonoid(S) or IsFpSemigroup(S) then + return function(x) + if IsOne(x) then + return "ε"; + fi; + return ReplacedString(String(x), "*", ""); + end; + else + return function(x) + local ToExtRepObj, ToString; + ToExtRepObj := SEMIGROUPS.WordToExtRepObj; + ToString := x -> SEMIGROUPS.ExtRepObjToString(x, names); + if IsOne(x) then + return "ε"; + fi; + return ToString(ToExtRepObj(MinimalMonoidFactorization(S, x))); + end; + fi; +end; + +# This method exists so that we use the same letters as S in the output. +InstallMethod(GraphvizLeftCayleyDigraph, "for an fp monoid", [IsFpMonoid], +function(S) + local label, D, pos, x; + + Info(InfoWarning, + 1, + "GraphvizLeftCayleyDigraph: using GeneratorsOfMonoid ", + "instead of GeneratorsOfSemigroup"); + + label := SEMIGROUPS.HTMLSemigroupElement(S, fail); + + # TODO replace with LeftCayleyDigraph(S, SomeElements) method instead + D := DigraphMutableCopy(LeftCayleyDigraph(S)); + pos := Position(GeneratorsOfSemigroup(S), One(S)); + for x in OutNeighbours(D) do + Remove(x, pos); od; + MakeImmutable(D); - Append(str, " % Edges . . .\n"); - nbs := OutNeighbours(digraph); - for from in [1 .. Size(S)] do - for gen in [1 .. Size(nbs[from])] do - Append(str, edge(from, nbs[from][gen], gen)); + return GraphvizWordGraph(D, + List(S, label), + List(GeneratorsOfMonoid(S), label)); +end); + +######################################################################## +# GraphvizRightCayleyDigraph +######################################################################## + +InstallMethod(GraphvizRightCayleyDigraph, +"for a semigroup and list of generator names", +[IsSemigroup and CanUseFroidurePin, IsHomogeneousList], +function(S, names) + local pos, ToExtRepObj, ToString, label; + + if Length(GeneratorsOfSemigroup(S)) <> Length(names) then + ErrorNoReturn("the 2nd argument (list of names) must have ", + "length equal to Length(GeneratorsOfSemigroup(S)) = ", + Length(GeneratorsOfSemigroup(S)), + "where S is the 1st argument (a semigroup)", + ", but found ", Length(names)); + elif not IsString(names[1]) then + ErrorNoReturn("the 2nd argument (list of names) must consist of ", + "strings, but found ", TNAM_OBJ(names[1])); + fi; + + if IsMonoidAsSemigroup(S) then + S := AsMonoid(S); + pos := Position(GeneratorsOfSemigroup(S), One(S)); + if pos <> fail then + names := ShallowCopy(names); + Remove(names, pos); + fi; + return GraphvizRightCayleyDigraph(S, names); + fi; + ToExtRepObj := SEMIGROUPS.WordToExtRepObj; + ToString := x -> SEMIGROUPS.ExtRepObjToString(x, names); + label := x -> ToString(ToExtRepObj(MinimalFactorization(S, x))); + return GraphvizWordGraph(RightCayleyDigraph(S), + List(S, label), + List(GeneratorsOfSemigroup(S), label)); +end); + +InstallMethod(GraphvizRightCayleyDigraph, "for a monoid", +[IsMonoid and CanUseFroidurePin, IsHomogeneousList], +function(S, names) + local label, pos, D, x; + + if Length(GeneratorsOfMonoid(S)) <> Length(names) then + ErrorNoReturn("the 2nd argument (list of names) must have ", + "length equal to Length(GeneratorsOfMonoid(S)) = ", + Length(GeneratorsOfMonoid(S)), + "where S is the 1st argument (a monoid)", + ", but found ", Length(names)); + elif not IsString(names[1]) then + ErrorNoReturn("the 2nd argument (list of names) must consist of ", + "strings, but found ", TNAM_OBJ(names[1])); + fi; + + Info(InfoWarning, + 1, + "GraphvizRightCayleyDigraph: using GeneratorsOfMonoid ", + "instead of GeneratorsOfSemigroup"); + + label := SEMIGROUPS.HTMLSemigroupElement(S, names); + # TODO replace with RightCayleyDigraph(S, SomeElements) method instead + pos := Position(GeneratorsOfSemigroup(S), One(S)); + D := RightCayleyDigraph(S); + if pos <> fail then + D := DigraphMutableCopy(D); + for x in OutNeighbours(D) do + Remove(x, pos); od; + MakeImmutable(D); + fi; + return GraphvizWordGraph(D, + List(S, label), + List(GeneratorsOfMonoid(S), label)); +end); + +InstallMethod(GraphvizRightCayleyDigraph, "for a semigroup", [IsSemigroup], +function(S) + local names; + + names := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + names := List([1 .. Size(GeneratorsOfSemigroup(S))], x -> [names[x]]); + + Info(InfoWarning, 1, "GraphvizRightCayleyDigraph: no generator labels ", + "specified, using ", names, " for GeneratorsOfSemigroup"); + + return GraphvizRightCayleyDigraph(S, names); +end); + +# The next method doesn't really need to exist but the info warnings make more +# sense with it. +InstallMethod(GraphvizRightCayleyDigraph, "for a monoid", [IsMonoid], +function(S) + local names; + + names := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"; + names := List([1 .. Size(GeneratorsOfMonoid(S))], x -> [names[x]]); + + Info(InfoWarning, 1, "GraphvizRightCayleyDigraph: no generator labels ", + "specified, using ", names, " for GeneratorsOfMonoid"); + + return GraphvizRightCayleyDigraph(S, names); +end); + +# This method exists so that we use the same letters as S in the output. +InstallMethod(GraphvizRightCayleyDigraph, "for an fp semigroup", [IsFpSemigroup], +function(S) + local label; + + label := x -> ReplacedString(String(x), "*", ""); + return GraphvizWordGraph(RightCayleyDigraph(S), + List(S, label), + List(GeneratorsOfSemigroup(S), label)); +end); + +# This method exists so that we use the same letters as S in the output. +InstallMethod(GraphvizRightCayleyDigraph, "for an fp monoid", [IsFpMonoid], +function(S) + local label, D, pos, x; + + Info(InfoWarning, + 1, + "GraphvizRightCayleyDigraph: using GeneratorsOfMonoid ", + "instead of GeneratorsOfSemigroup"); + + label := SEMIGROUPS.HTMLSemigroupElement(S, fail); + + # TODO replace with RightCayleyDigraph(S, SomeElements) method instead + D := DigraphMutableCopy(RightCayleyDigraph(S)); + pos := Position(GeneratorsOfSemigroup(S), One(S)); + for x in OutNeighbours(D) do + Remove(x, pos); od; + MakeImmutable(D); - Append(str, "\\end{tikzpicture}"); - return str; + return GraphvizWordGraph(D, + List(S, label), + List(GeneratorsOfMonoid(S), label)); end); -InstallMethod(DotString, "for a Cayley digraph", [IsCayleyDigraph], -function(digraph) - local S, li, label, i; - S := SemigroupOfCayleyDigraph(digraph); - if not CanUseFroidurePin(S) or Size(S) > 26 then - TryNextMethod(); +######################################################################## +# GraphvizWordGraph +######################################################################## + +InstallMethod(GraphvizWordGraph, +"for a word graph, list of node labels, and list of edge labels", +[IsDigraph, IsHomogeneousList, IsHomogeneousList], +function(D, node_labels, edge_labels) + local M, N, edge_colors, gv, pos, legend, start_table, end_table, row, label, + e, m, i; + + if not DigraphHasAVertex(D) then + # Word graphs must have at least one node . . . + ErrorNoReturn("the 1st argument (a digraph) must have at least 1 vertex"); + elif not IsOutRegularDigraph(D) then + ErrorNoReturn("the 1st argument (a digraph) must be out-regular"); + fi; + + M := DigraphNrVertices(D); + N := Length(OutNeighboursOfVertex(D, 1)); + if Length(node_labels) <> M then + ErrorFormatted("expected the 2nd argument (list of node labels) ", + "to have length {}, but found {}", + M, + Length(node_labels)); + elif not IsString(node_labels[1]) then + ErrorFormatted("expected the 2nd argument (list of node labels) ", + "to consist of strings, found {}", + TNAM_OBJ(node_labels[1])); + elif Length(edge_labels) <> N then + ErrorFormatted("expected the 3rd argument (list of edge labels) ", + "to have length {}, but found {}", + N, + Length(edge_labels)); + elif not IsString(edge_labels[1]) then + ErrorFormatted("expected the 3rd argument (list of edge labels) ", + "to consist of strings, found {}", + TNAM_OBJ(node_labels[1])); + fi; + + # TODO longer list here + edge_colors := ["#00ff00", "#ff00ff", "#007fff", "#ff7f00", + "#7fbf7f", "#4604ac", "#de0328", "#19801d", + "#d881f5", "#00ffff", "#ffff00", "#00ff7f", + "#ad5867", "#85f610", "#84e9f5", "#f5c778", + "#207090", "#764ef3", "#7b4c00", "#0000ff", + "#b80c9a", "#601045", "#29b7c0", "#839f12"]; + + if N > Length(edge_colors) then + ErrorFormatted("the 1st argument (an out-regular digraph) must have ", + "out-degree at most {}, found {}", + Length(edge_colors), + N); fi; - li := AsListCanonical(S); - for i in [1 .. Size(S)] do - label := SEMIGROUPS.WordToExtRepObj(MinimalFactorization(S, li[i])); - label := SEMIGROUPS.ExtRepObjToString(label); - SetDigraphVertexLabel(digraph, i, label); + + edge_colors := edge_colors{[1 .. N]}; + # TODO some of the checks above are probably duplicated in SetNodeLabels, and + # in GraphvizEdgeColoredDigraph + gv := GraphvizEdgeColoredDigraph(D, + ListWithIdenticalEntries(DigraphNrVertices(D), + edge_colors)); + GraphvizSetNodeLabels(gv, node_labels); + GraphvizSetAttr(gv, "node [shape=\"box\"]"); + for m in [1 .. M] do + pos := Position(edge_labels, node_labels[m]); + if pos <> fail then + GraphvizSetAttr(GraphvizNode(gv, m), "color", edge_colors[pos]); + GraphvizSetAttr(GraphvizNode(gv, m), "style", "filled"); + fi; od; - return DotVertexLabelledDigraph(digraph); -end); -InstallMethod(DotLeftCayleyDigraph, "for a semigroup", [IsSemigroup], -S -> DotString(LeftCayleyDigraph(S))); + legend := GraphvizAddContext(gv, "legend"); + GraphvizSetAttr(legend, "node [shape=plaintext]"); + legend := GraphvizAddSubgraph(legend, "legend"); + + start_table := Concatenation("<\n"); + end_table := "
>\n"; + + row := {index, content} -> StringFormatted( + "{} \n", + index, + content); + + # HTML table for the head of the arrows in the legend + label := Concatenation(ShallowCopy(start_table), + Concatenation(List([1 .. N], + i -> row(i, edge_labels[i]))), + end_table); + GraphvizSetAttr(GraphvizAddNode(legend, "head"), "label", label); + + # HTML table for the tail of the arrows in the legend + label := Concatenation(start_table, + Concatenation(List([1 .. N], i -> row(i, ""))), + end_table); + GraphvizSetAttr(GraphvizAddNode(legend, "tail"), "label", label); + + # The actual arrows from the head to the tail + for i in [1 .. N] do + e := GraphvizAddEdge(legend, + StringFormatted("head:port{}:e", i), + StringFormatted("tail:port{}:w", i)); + GraphvizSetAttr(e, "color", edge_colors[i]); + GraphvizSetAttr(e, "constraint", false); + od; -InstallMethod(DotRightCayleyDigraph, "for a semigroup", [IsSemigroup], -S -> DotString(RightCayleyDigraph(S))); + return gv; +end); diff --git a/tst/standard/semigroups/semifp.tst b/tst/standard/semigroups/semifp.tst index 665af9739..13aaa8c76 100644 --- a/tst/standard/semigroups/semifp.tst +++ b/tst/standard/semigroups/semifp.tst @@ -2068,7 +2068,8 @@ Error, the argument be at most 52 gap> SEMIGROUPS.ExtRepObjToString(SEMIGROUPS.WordToExtRepObj(w)); "a ^ 100b ^ 50ca ^ 8" gap> SEMIGROUPS.ExtRepObjToString([100, 1]); -Error, the maximum value in an odd position of the argument must be at most 52 +Error, the maximum value in an odd position of the argument must be at most +52 found 100 # Test IsomorphismFpSemigroup (for factorizable inverse monoids) gap> S := SymmetricInverseMonoid(4);; diff --git a/tst/standard/tools/display.tst b/tst/standard/tools/display.tst index e04dfb2dc..9a05064c4 100644 --- a/tst/standard/tools/display.tst +++ b/tst/standard/tools/display.tst @@ -20,152 +20,104 @@ gap> SEMIGROUPS.StartTest();; # Test TikzString for a pbr gap> TikzString(PBR([[-2, 2], [1, 2], [-1, 2]], [[-3], [1, 2], [- 3]])); -"1\n2\n3\n4\n5\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=bla\ -ck, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14\ -cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/\ -.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \ - \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\\ -node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\ -\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1\ -.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) to (-2);\n \\arc (1) .\ -. controls (1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, \ -2.3333333333333335) .. (2);\n\n % arcs from vertex -1\n \\arc (-1) .. contro\ -ls (1.4666666666666668, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (\ --3);\n\n % arcs from vertex 2\n \\arc (2) .. controls (0.93333333333333324, \ -2.3333333333333335) and (1.0666666666666667, 2.3333333333333335) .. (1);\n \\\ -arc (2) edge [toploop] (2);\n\n % arcs from vertex -2\n \\arc (-2) to (1);\n\ - \\arc (-2) to (2);\n\n % arcs from vertex 3\n \\arc (3) to (-1);\n \\arc \ -(3) .. controls (1.6000000000000001, 2.3333333333333335) and (1.73333333333333\ -34, 2.3333333333333335) .. (2);\n\n % arcs from vertex -3\n \\arc (-3) edge \ -[botloop] (-3);\n\n\\end{tikzpicture}\n\\end{document}" +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\\usetikzlibrary{arrows\ +}\n\\usetikzlibrary{arrows.meta}\n\\newcommand{\\arc}{\\draw[semithick, -{>[wi\ +dth = 1.5mm, length = 2.5mm]}]}\n\n\\begin{document}\\begin{tikzpicture}[\n v\ +ertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.style={c\ +ircle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm\ +, out = -70, in = -110},\n toploop/.style={min distance = 8mm, out = 70, in =\ + 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \\node \ +[vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n \ +}\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n\ + \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n\ + \\arc (1) to (-2);\n \\arc (1) .. controls (1.0666666666666667, 2.333333333\ +3333335) and (0.93333333333333324, 2.3333333333333335) .. (2);\n\n % arcs fro\ +m vertex -1\n \\arc (-1) .. controls (1.4666666666666668, 1.0833333333333335)\ + and (1.2, 1.0833333333333335) .. (-3);\n\n % arcs from vertex 2\n \\arc (2)\ + .. controls (0.93333333333333324, 2.3333333333333335) and (1.0666666666666667\ +, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n\n % arcs fro\ +m vertex -2\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n\n % arcs from verte\ +x 3\n \\arc (3) to (-1);\n \\arc (3) .. controls (1.6000000000000001, 2.3333\ +333333333335) and (1.7333333333333334, 2.3333333333333335) .. (2);\n\n % arcs\ + from vertex -3\n \\arc (-3) edge [botloop] (-3);\n\n\\end{tikzpicture}\n\\en\ +d{document}" gap> TikzString(PBR([[-2, 2], [1, 2], [-1, 2]], [[-3], [1, 2], [- 3]]), > rec(labels := true)); -"1\n2\n3\n4\n5\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=bla\ -ck, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14\ -cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/\ -.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \ - \\foreach \\i in {1,...,3} {\n \\node [vertex, label={[yshift=9mm]\\i}] at\ - (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\fo\ -reach \\i in {1,...,3} {\n \\node [vertex, label={[yshift=-15mm,xshift=-0.5\ -mm]-\\i}] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n\ - }\n\n % arcs from vertex 1\n \\arc (1) to (-2);\n \\arc (1) .. controls (\ -1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, 2.3333333333\ -333335) .. (2);\n\n % arcs from vertex -1\n \\arc (-1) .. controls (1.466666\ -6666666668, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (-3);\n\n % \ -arcs from vertex 2\n \\arc (2) .. controls (0.93333333333333324, 2.3333333333\ -333335) and (1.0666666666666667, 2.3333333333333335) .. (1);\n \\arc (2) edge\ - [toploop] (2);\n\n % arcs from vertex -2\n \\arc (-2) to (1);\n \\arc (-2)\ - to (2);\n\n % arcs from vertex 3\n \\arc (3) to (-1);\n \\arc (3) .. contr\ -ols (1.6000000000000001, 2.3333333333333335) and (1.7333333333333334, 2.333333\ -3333333335) .. (2);\n\n % arcs from vertex -3\n \\arc (-3) edge [botloop] (-\ -3);\n\n\\end{tikzpicture}\n\\end{document}" +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\\usetikzlibrary{arrows\ +}\n\\usetikzlibrary{arrows.meta}\n\\newcommand{\\arc}{\\draw[semithick, -{>[wi\ +dth = 1.5mm, length = 2.5mm]}]}\n\n\\begin{document}\\begin{tikzpicture}[\n v\ +ertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.style={c\ +ircle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm\ +, out = -70, in = -110},\n toploop/.style={min distance = 8mm, out = 70, in =\ + 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \\node \ +[vertex, label={[yshift=9mm]\\i}] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i\ +) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vert\ +ex, label={[yshift=-15mm,xshift=-0.5mm]-\\i}] at (\\i/1.5, 0) {};\n \\node \ +[ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1)\ + to (-2);\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333333335) an\ +d (0.93333333333333324, 2.3333333333333335) .. (2);\n\n % arcs from vertex -1\ +\n \\arc (-1) .. controls (1.4666666666666668, 1.0833333333333335) and (1.2, \ +1.0833333333333335) .. (-3);\n\n % arcs from vertex 2\n \\arc (2) .. control\ +s (0.93333333333333324, 2.3333333333333335) and (1.0666666666666667, 2.3333333\ +333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n\n % arcs from vertex -2\ +\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n\n % arcs from vertex 3\n \\ar\ +c (3) to (-1);\n \\arc (3) .. controls (1.6000000000000001, 2.333333333333333\ +5) and (1.7333333333333334, 2.3333333333333335) .. (2);\n\n % arcs from verte\ +x -3\n \\arc (-3) edge [botloop] (-3);\n\n\\end{tikzpicture}\n\\end{document}\ +" # TikzString for a pbr collection gap> x := PBR([[1], [], []], [[2], [-2, 1, 2], [1, 2, 3]]);; gap> y := PBR([[-3, -2, -1, 2], [-3, -2, -1, 1, 2, 3], [-3, -2, -1, 1, 2, 3]], > [[-3, -2, -1, 2], [-3, -2, -1, 1, 3], [-3, -2, -1, 1, 2, 3]]);; gap> TikzString(Semigroup(x, y)); -"1\n2\n3\n4\n5\n\\begin{center}\n\\begin{tikzpicture}[\n vertex/.style={circl\ -e, draw, fill=black, inner sep =0.04cm},\n ghost/.style={circle, draw = none,\ - inner sep = 0.14cm},\n botloop/.style={min distance = 8mm, out = -70, in = -\ -110},\n toploop/.style={min distance = 8mm, out = 70, in = 110}]\n\n % verti\ -ces and labels\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.\ -5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\\ -i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] \ -(-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edge [t\ -oploop] (1);\n\n % arcs from vertex -1\n \\arc (-1) to (2);\n\n % arcs from\ - vertex 2\n\n % arcs from vertex -2\n \\arc (-2) edge [botloop] (-2);\n \\a\ -rc (-2) to (1);\n \\arc (-2) to (2);\n\n % arcs from vertex 3\n\n % arcs fr\ -om vertex -3\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\ -\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n verte\ -x/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.style={circl\ -e, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm, ou\ -t = -70, in = -110},\n toploop/.style={min distance = 8mm, out = 70, in = 110\ -}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \\node [ver\ -tex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\ -\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \ - \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \ -\\arc (1) to (-3);\n \\arc (1) to (-2);\n \\arc (1) to (-1);\n \\arc (1) ..\ - controls (1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, 2\ -.3333333333333335) .. (2);\n\n % arcs from vertex -1\n \\arc (-1) .. control\ -s (1.4666666666666668, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (-\ -3);\n \\arc (-1) .. controls (1.0666666666666667, 0.66666666666666674) and (0\ -.93333333333333324, 0.66666666666666674) .. (-2);\n \\arc (-1) edge [botloop]\ - (-1);\n \\arc (-1) to (2);\n\n % arcs from vertex 2\n \\arc (2) to (-3);\n\ - \\arc (2) to (-2);\n \\arc (2) to (-1);\n \\arc (2) .. controls (0.9333333\ -3333333324, 2.3333333333333335) and (1.0666666666666667, 2.3333333333333335) .\ -. (1);\n \\arc (2) edge [toploop] (2);\n \\arc (2) .. controls (1.7333333333\ -333334, 2.3333333333333335) and (1.6000000000000001, 2.3333333333333335) .. (3\ -);\n\n % arcs from vertex -2\n \\arc (-2) .. controls (1.7333333333333334, 0\ -.66666666666666674) and (1.6000000000000001, 0.66666666666666674) .. (-3);\n \ -\\arc (-2) edge [botloop] (-2);\n \\arc (-2) .. controls (0.93333333333333324\ -, 0.66666666666666674) and (1.0666666666666667, 0.66666666666666674) .. (-1);\ -\n \\arc (-2) to (1);\n \\arc (-2) to (3);\n\n % arcs from vertex 3\n \\ar\ -c (3) to (-3);\n \\arc (3) to (-2);\n \\arc (3) to (-1);\n \\arc (3) .. con\ -trols (1.2, 1.9166666666666665) and (1.4666666666666668, 1.9166666666666665) .\ -. (1);\n \\arc (3) .. controls (1.6000000000000001, 2.3333333333333335) and (\ -1.7333333333333334, 2.3333333333333335) .. (2);\n \\arc (3) edge [toploop] (3\ -);\n\n % arcs from vertex -3\n \\arc (-3) edge [botloop] (-3);\n \\arc (-3)\ - .. controls (1.6000000000000001, 0.66666666666666674) and (1.7333333333333334\ -, 0.66666666666666674) .. (-2);\n \\arc (-3) .. controls (1.2, 1.083333333333\ -3335) and (1.4666666666666668, 1.0833333333333335) .. (-1);\n \\arc (-3) to (\ -1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\big\ -skip\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=bl\ -ack, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.1\ -4cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop\ -/.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n\ - \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \ -\\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} \ -{\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/\ -1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edge [toploop] (1);\n\ -\n % arcs from vertex -1\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n\n % a\ -rcs from vertex 2\n\n % arcs from vertex -2\n \\arc (-2) edge [botloop] (-2)\ -;\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n\n % arcs from vertex 3\n\n %\ - arcs from vertex -3\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3)\ - to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\ -\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.sty\ -le={circle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance \ -= 8mm, out = -70, in = -110},\n toploop/.style={min distance = 8mm, out = 70,\ - in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \\\ -node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {}\ -;\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) \ -{};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from verte\ -x 1\n \\arc (1) edge [toploop] (1);\n\n % arcs from vertex -1\n \\arc (-1) \ -.. controls (1.4666666666666668, 1.0833333333333335) and (1.2, 1.0833333333333\ -335) .. (-3);\n \\arc (-1) .. controls (1.0666666666666667, 0.666666666666666\ -74) and (0.93333333333333324, 0.66666666666666674) .. (-2);\n \\arc (-1) edge\ - [botloop] (-1);\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) to \ -(3);\n\n % arcs from vertex 2\n\n % arcs from vertex -2\n \\arc (-2) .. con\ -trols (1.7333333333333334, 0.66666666666666674) and (1.6000000000000001, 0.666\ -66666666666674) .. (-3);\n \\arc (-2) edge [botloop] (-2);\n \\arc (-2) .. c\ -ontrols (0.93333333333333324, 0.66666666666666674) and (1.0666666666666667, 0.\ -66666666666666674) .. (-1);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \\a\ -rc (-2) to (3);\n\n % arcs from vertex 3\n\n % arcs from vertex -3\n \\arc \ -(-3) edge [botloop] (-3);\n \\arc (-3) .. controls (1.6000000000000001, 0.666\ -66666666666674) and (1.7333333333333334, 0.66666666666666674) .. (-2);\n \\ar\ -c (-3) .. controls (1.2, 1.0833333333333335) and (1.4666666666666668, 1.083333\ -3333333335) .. (-1);\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3)\ - to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\ -\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.sty\ -le={circle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance \ -= 8mm, out = -70, in = -110},\n toploop/.style={min distance = 8mm, out = 70,\ - in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \\\ -node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {}\ -;\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) \ -{};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from verte\ -x 1\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333333335) and (0.9\ -3333333333333324, 2.3333333333333335) .. (2);\n\n % arcs from vertex -1\n \\\ -arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from \ -vertex 2\n \\arc (2) .. controls (0.93333333333333324, 2.3333333333333335) an\ -d (1.0666666666666667, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop]\ - (2);\n \\arc (2) .. controls (1.7333333333333334, 2.3333333333333335) and (1\ -.6000000000000001, 2.3333333333333335) .. (3);\n\n % arcs from vertex -2\n \ -\\arc (-2) edge [botloop] (-2);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \ - \\arc (-2) to (3);\n\n % arcs from vertex 3\n \\arc (3) .. controls (1.2, 1\ -.9166666666666665) and (1.4666666666666668, 1.9166666666666665) .. (1);\n \\a\ -rc (3) .. controls (1.6000000000000001, 2.3333333333333335) and (1.73333333333\ -33334, 2.3333333333333335) .. (2);\n \\arc (3) edge [toploop] (3);\n\n % arc\ -s from vertex -3\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to \ +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\\usetikzlibrary{arrows\ +}\n\\usetikzlibrary{arrows.meta}\n\\newcommand{\\arc}{\\draw[semithick, -{>[wi\ +dth = 1.5mm, length = 2.5mm]}]}\n\n\\begin{document}\\begin{center}\n\\begin{t\ +ikzpicture}[\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n\ + ghost/.style={circle, draw = none, inner sep = 0.14cm},\n botloop/.style={m\ +in distance = 8mm, out = -70, in = -110},\n toploop/.style={min distance = 8m\ +m, out = 70, in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,\ +3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\\ +i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\ +\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arc\ +s from vertex 1\n \\arc (1) edge [toploop] (1);\n\n % arcs from vertex -1\n \ + \\arc (-1) to (2);\n\n % arcs from vertex 2\n\n % arcs from vertex -2\n \\\ +arc (-2) edge [botloop] (-2);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n\n \ + % arcs from vertex 3\n\n % arcs from vertex -3\n \\arc (-3) to (1);\n \\ar\ +c (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigsk\ +ip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=black, inner \ +sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14cm},\n bo\ +tloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/.style={mi\ +n distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \\foreach\ + \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghos\ +t] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\nod\ +e [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\ +\n }\n\n % arcs from vertex 1\n \\arc (1) to (-3);\n \\arc (1) to (-2);\n \ + \\arc (1) to (-1);\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333\ +333335) and (0.93333333333333324, 2.3333333333333335) .. (2);\n\n % arcs from\ + vertex -1\n \\arc (-1) .. controls (1.4666666666666668, 1.0833333333333335) \ +and (1.2, 1.0833333333333335) .. (-3);\n \\arc (-1) .. controls (1.0666666666\ +666667, 0.66666666666666674) and (0.93333333333333324, 0.66666666666666674) ..\ + (-2);\n \\arc (-1) edge [botloop] (-1);\n \\arc (-1) to (2);\n\n % arcs fr\ +om vertex 2\n \\arc (2) to (-3);\n \\arc (2) to (-2);\n \\arc (2) to (-1);\ +\n \\arc (2) .. controls (0.93333333333333324, 2.3333333333333335) and (1.066\ +6666666666667, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n \ + \\arc (2) .. controls (1.7333333333333334, 2.3333333333333335) and (1.6000000\ +000000001, 2.3333333333333335) .. (3);\n\n % arcs from vertex -2\n \\arc (-2\ +) .. controls (1.7333333333333334, 0.66666666666666674) and (1.600000000000000\ +1, 0.66666666666666674) .. (-3);\n \\arc (-2) edge [botloop] (-2);\n \\arc (\ +-2) .. controls (0.93333333333333324, 0.66666666666666674) and (1.066666666666\ +6667, 0.66666666666666674) .. (-1);\n \\arc (-2) to (1);\n \\arc (-2) to (3)\ +;\n\n % arcs from vertex 3\n \\arc (3) to (-3);\n \\arc (3) to (-2);\n \\a\ +rc (3) to (-1);\n \\arc (3) .. controls (1.2, 1.9166666666666665) and (1.4666\ +666666666668, 1.9166666666666665) .. (1);\n \\arc (3) .. controls (1.60000000\ +00000001, 2.3333333333333335) and (1.7333333333333334, 2.3333333333333335) .. \ +(2);\n \\arc (3) edge [toploop] (3);\n\n % arcs from vertex -3\n \\arc (-3)\ + edge [botloop] (-3);\n \\arc (-3) .. controls (1.6000000000000001, 0.6666666\ +6666666674) and (1.7333333333333334, 0.66666666666666674) .. (-2);\n \\arc (-\ +3) .. controls (1.2, 1.0833333333333335) and (1.4666666666666668, 1.0833333333\ +333335) .. (-1);\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to \ (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n v\ ertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost/.style={c\ ircle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm\ @@ -174,780 +126,468 @@ ircle, draw = none, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm\ [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n \ }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n\ \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n\ - \\arc (1) to (-3);\n \\arc (1) to (-2);\n \\arc (1) to (-1);\n \\arc (1) \ -edge [toploop] (1);\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333\ -333335) and (0.93333333333333324, 2.3333333333333335) .. (2);\n \\arc (1) .. \ -controls (1.4666666666666668, 1.9166666666666665) and (1.2, 1.9166666666666665\ -) .. (3);\n\n % arcs from vertex -1\n \\arc (-1) .. controls (1.466666666666\ -6668, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (-3);\n \\arc (-1)\ - .. controls (1.0666666666666667, 0.66666666666666674) and (0.9333333333333332\ -4, 0.66666666666666674) .. (-2);\n \\arc (-1) edge [botloop] (-1);\n \\arc (\ --1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from verte\ -x 2\n \\arc (2) to (-3);\n \\arc (2) to (-2);\n \\arc (2) to (-1);\n \\arc\ - (2) .. controls (0.93333333333333324, 2.3333333333333335) and (1.066666666666\ -6667, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n \\arc (2\ -) .. controls (1.7333333333333334, 2.3333333333333335) and (1.6000000000000001\ -, 2.3333333333333335) .. (3);\n\n % arcs from vertex -2\n \\arc (-2) .. cont\ -rols (1.7333333333333334, 0.66666666666666674) and (1.6000000000000001, 0.6666\ -6666666666674) .. (-3);\n \\arc (-2) edge [botloop] (-2);\n \\arc (-2) .. co\ -ntrols (0.93333333333333324, 0.66666666666666674) and (1.0666666666666667, 0.6\ -6666666666666674) .. (-1);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \\ar\ -c (-2) to (3);\n\n % arcs from vertex 3\n \\arc (3) to (-3);\n \\arc (3) to\ - (-2);\n \\arc (3) to (-1);\n \\arc (3) .. controls (1.2, 1.9166666666666665\ -) and (1.4666666666666668, 1.9166666666666665) .. (1);\n \\arc (3) .. control\ -s (1.6000000000000001, 2.3333333333333335) and (1.7333333333333334, 2.33333333\ -33333335) .. (2);\n \\arc (3) edge [toploop] (3);\n\n % arcs from vertex -3\ -\n \\arc (-3) edge [botloop] (-3);\n \\arc (-3) .. controls (1.6000000000000\ -001, 0.66666666666666674) and (1.7333333333333334, 0.66666666666666674) .. (-2\ -);\n \\arc (-3) .. controls (1.2, 1.0833333333333335) and (1.4666666666666668\ -, 1.0833333333333335) .. (-1);\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \ -\\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikz\ -picture}[\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n g\ -host/.style={circle, draw = none, inner sep = 0.14cm},\n botloop/.style={min \ -distance = 8mm, out = -70, in = -110},\n toploop/.style={min distance = 8mm, \ -out = 70, in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} \ -{\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1\ -.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i\ -/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs f\ -rom vertex 1\n \\arc (1) edge [toploop] (1);\n\n % arcs from vertex -1\n \\\ -arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from \ -vertex 2\n\n % arcs from vertex -2\n \\arc (-2) edge [botloop] (-2);\n \\ar\ -c (-2) to (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from ve\ -rtex 3\n\n % arcs from vertex -3\n \\arc (-3) to (1);\n \\arc (-3) to (2);\ -\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{\ -tikzpicture}[\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\ -\n ghost/.style={circle, draw = none, inner sep = 0.14cm},\n botloop/.style=\ -{min distance = 8mm, out = -70, in = -110},\n toploop/.style={min distance = \ -8mm, out = 70, in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,..\ -.,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\ -\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at\ - (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % a\ -rcs from vertex 1\n \\arc (1) .. controls (1.0666666666666667, 2.333333333333\ -3335) and (0.93333333333333324, 2.3333333333333335) .. (2);\n\n % arcs from v\ -ertex -1\n \\arc (-1) .. controls (1.4666666666666668, 1.0833333333333335) an\ -d (1.2, 1.0833333333333335) .. (-3);\n \\arc (-1) .. controls (1.066666666666\ -6667, 0.66666666666666674) and (0.93333333333333324, 0.66666666666666674) .. (\ --2);\n \\arc (-1) edge [botloop] (-1);\n \\arc (-1) to (1);\n \\arc (-1) to\ - (2);\n \\arc (-1) to (3);\n\n % arcs from vertex 2\n \\arc (2) .. controls\ - (0.93333333333333324, 2.3333333333333335) and (1.0666666666666667, 2.33333333\ -33333335) .. (1);\n \\arc (2) edge [toploop] (2);\n \\arc (2) .. controls (1\ -.7333333333333334, 2.3333333333333335) and (1.6000000000000001, 2.333333333333\ -3335) .. (3);\n\n % arcs from vertex -2\n \\arc (-2) .. controls (1.73333333\ -33333334, 0.66666666666666674) and (1.6000000000000001, 0.66666666666666674) .\ -. (-3);\n \\arc (-2) edge [botloop] (-2);\n \\arc (-2) .. controls (0.933333\ -33333333324, 0.66666666666666674) and (1.0666666666666667, 0.66666666666666674\ -) .. (-1);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\ -\n % arcs from vertex 3\n \\arc (3) .. controls (1.2, 1.9166666666666665) an\ -d (1.4666666666666668, 1.9166666666666665) .. (1);\n \\arc (3) .. controls (1\ -.6000000000000001, 2.3333333333333335) and (1.7333333333333334, 2.333333333333\ -3335) .. (2);\n \\arc (3) edge [toploop] (3);\n\n % arcs from vertex -3\n \ -\\arc (-3) edge [botloop] (-3);\n \\arc (-3) .. controls (1.6000000000000001,\ - 0.66666666666666674) and (1.7333333333333334, 0.66666666666666674) .. (-2);\n\ - \\arc (-3) .. controls (1.2, 1.0833333333333335) and (1.4666666666666668, 1.\ -0833333333333335) .. (-1);\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\ar\ -c (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpict\ -ure}[\n vertex/.style={circle, draw, fill=black, inner sep =0.04cm},\n ghost\ -/.style={circle, draw = none, inner sep = 0.14cm},\n botloop/.style={min dist\ -ance = 8mm, out = -70, in = -110},\n toploop/.style={min distance = 8mm, out \ -= 70, in = 110}]\n\n % vertices and labels\n \\foreach \\i in {1,...,3} {\n \ - \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, \ -3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5\ -, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from \ -vertex 1\n \\arc (1) edge [toploop] (1);\n \\arc (1) .. controls (1.06666666\ -66666667, 2.3333333333333335) and (0.93333333333333324, 2.3333333333333335) ..\ - (2);\n \\arc (1) .. controls (1.4666666666666668, 1.9166666666666665) and (1\ -.2, 1.9166666666666665) .. (3);\n\n % arcs from vertex -1\n \\arc (-1) to (1\ -);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from vertex 2\n \\\ -arc (2) .. controls (0.93333333333333324, 2.3333333333333335) and (1.066666666\ -6666667, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n \\arc\ - (2) .. controls (1.7333333333333334, 2.3333333333333335) and (1.6000000000000\ -001, 2.3333333333333335) .. (3);\n\n % arcs from vertex -2\n \\arc (-2) edge\ - [botloop] (-2);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \\arc (-2) to \ -(3);\n\n % arcs from vertex 3\n \\arc (3) .. controls (1.2, 1.91666666666666\ -65) and (1.4666666666666668, 1.9166666666666665) .. (1);\n \\arc (3) .. contr\ -ols (1.6000000000000001, 2.3333333333333335) and (1.7333333333333334, 2.333333\ -3333333335) .. (2);\n \\arc (3) edge [toploop] (3);\n\n % arcs from vertex -\ -3\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{t\ -ikzpicture}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={c\ -ircle, draw, fill=black, inner sep =0.04cm},\n ghost/.style={circle, draw = n\ -one, inner sep = 0.14cm},\n botloop/.style={min distance = 8mm, out = -70, in\ - = -110},\n toploop/.style={min distance = 8mm, out = 70, in = 110}]\n\n % v\ -ertices and labels\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\\ -i/1.5, 3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreac\ -h \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [gho\ -st] (-\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edg\ -e [toploop] (1);\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333333\ -335) and (0.93333333333333324, 2.3333333333333335) .. (2);\n \\arc (1) .. con\ -trols (1.4666666666666668, 1.9166666666666665) and (1.2, 1.9166666666666665) .\ -. (3);\n\n % arcs from vertex -1\n \\arc (-1) .. controls (1.466666666666666\ -8, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (-3);\n \\arc (-1) ..\ - controls (1.0666666666666667, 0.66666666666666674) and (0.93333333333333324, \ -0.66666666666666674) .. (-2);\n \\arc (-1) edge [botloop] (-1);\n \\arc (-1)\ - to (1);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from vertex 2\ -\n \\arc (2) .. controls (0.93333333333333324, 2.3333333333333335) and (1.066\ -6666666666667, 2.3333333333333335) .. (1);\n \\arc (2) edge [toploop] (2);\n \ - \\arc (2) .. controls (1.7333333333333334, 2.3333333333333335) and (1.6000000\ -000000001, 2.3333333333333335) .. (3);\n\n % arcs from vertex -2\n \\arc (-2\ -) .. controls (1.7333333333333334, 0.66666666666666674) and (1.600000000000000\ -1, 0.66666666666666674) .. (-3);\n \\arc (-2) edge [botloop] (-2);\n \\arc (\ --2) .. controls (0.93333333333333324, 0.66666666666666674) and (1.066666666666\ -6667, 0.66666666666666674) .. (-1);\n \\arc (-2) to (1);\n \\arc (-2) to (2)\ -;\n \\arc (-2) to (3);\n\n % arcs from vertex 3\n \\arc (3) .. controls (1.\ -2, 1.9166666666666665) and (1.4666666666666668, 1.9166666666666665) .. (1);\n \ - \\arc (3) .. controls (1.6000000000000001, 2.3333333333333335) and (1.7333333\ -333333334, 2.3333333333333335) .. (2);\n \\arc (3) edge [toploop] (3);\n\n %\ - arcs from vertex -3\n \\arc (-3) edge [botloop] (-3);\n \\arc (-3) .. contr\ -ols (1.6000000000000001, 0.66666666666666674) and (1.7333333333333334, 0.66666\ -666666666674) .. (-2);\n \\arc (-3) .. controls (1.2, 1.0833333333333335) and\ - (1.4666666666666668, 1.0833333333333335) .. (-1);\n \\arc (-3) to (1);\n \\\ -arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\big\ -skip\n\n\\end{center}\\end{document}" + \\arc (1) edge [toploop] (1);\n\n % arcs from vertex -1\n \\arc (-1) to (1\ +);\n \\arc (-1) to (2);\n\n % arcs from vertex 2\n\n % arcs from vertex -2\ +\n \\arc (-2) edge [botloop] (-2);\n \\arc (-2) to (1);\n \\arc (-2) to (2)\ +;\n\n % arcs from vertex 3\n\n % arcs from vertex -3\n \\arc (-3) to (1);\n\ + \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\ +\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=black,\ + inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14cm}\ +,\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/.st\ +yle={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \\\ +foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\nod\ +e [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \ + \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, \ +0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edge [toploop] (1);\n\n % \ +arcs from vertex -1\n \\arc (-1) .. controls (1.4666666666666668, 1.083333333\ +3333335) and (1.2, 1.0833333333333335) .. (-3);\n \\arc (-1) .. controls (1.0\ +666666666666667, 0.66666666666666674) and (0.93333333333333324, 0.666666666666\ +66674) .. (-2);\n \\arc (-1) edge [botloop] (-1);\n \\arc (-1) to (1);\n \\\ +arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs from vertex 2\n\n % arcs f\ +rom vertex -2\n \\arc (-2) .. controls (1.7333333333333334, 0.666666666666666\ +74) and (1.6000000000000001, 0.66666666666666674) .. (-3);\n \\arc (-2) edge \ +[botloop] (-2);\n \\arc (-2) .. controls (0.93333333333333324, 0.666666666666\ +66674) and (1.0666666666666667, 0.66666666666666674) .. (-1);\n \\arc (-2) to\ + (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from vertex 3\n\ +\n % arcs from vertex -3\n \\arc (-3) edge [botloop] (-3);\n \\arc (-3) .. \ +controls (1.6000000000000001, 0.66666666666666674) and (1.7333333333333334, 0.\ +66666666666666674) .. (-2);\n \\arc (-3) .. controls (1.2, 1.0833333333333335\ +) and (1.4666666666666668, 1.0833333333333335) .. (-1);\n \\arc (-3) to (1);\ +\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigski\ +p\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=black\ +, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14cm\ +},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/.s\ +tyle={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \ +\\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\n\ +ode [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n\ + \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5\ +, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) .. controls (1.0666666666\ +666667, 2.3333333333333335) and (0.93333333333333324, 2.3333333333333335) .. (\ +2);\n\n % arcs from vertex -1\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \ +\\arc (-1) to (3);\n\n % arcs from vertex 2\n \\arc (2) .. controls (0.93333\ +333333333324, 2.3333333333333335) and (1.0666666666666667, 2.3333333333333335)\ + .. (1);\n \\arc (2) edge [toploop] (2);\n \\arc (2) .. controls (1.73333333\ +33333334, 2.3333333333333335) and (1.6000000000000001, 2.3333333333333335) .. \ +(3);\n\n % arcs from vertex -2\n \\arc (-2) edge [botloop] (-2);\n \\arc (-\ +2) to (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from vertex\ + 3\n \\arc (3) .. controls (1.2, 1.9166666666666665) and (1.4666666666666668,\ + 1.9166666666666665) .. (1);\n \\arc (3) .. controls (1.6000000000000001, 2.3\ +333333333333335) and (1.7333333333333334, 2.3333333333333335) .. (2);\n \\arc\ + (3) edge [toploop] (3);\n\n % arcs from vertex -3\n \\arc (-3) to (1);\n \ +\\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\b\ +igskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fill=black, in\ +ner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep = 0.14cm},\n\ + botloop/.style={min distance = 8mm, out = -70, in = -110},\n toploop/.style\ +={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \\for\ +each \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [\ +ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \ +\\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0)\ + {};\n }\n\n % arcs from vertex 1\n \\arc (1) to (-3);\n \\arc (1) to (-2)\ +;\n \\arc (1) to (-1);\n \\arc (1) edge [toploop] (1);\n \\arc (1) .. contr\ +ols (1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, 2.33333\ +33333333335) .. (2);\n \\arc (1) .. controls (1.4666666666666668, 1.916666666\ +6666665) and (1.2, 1.9166666666666665) .. (3);\n\n % arcs from vertex -1\n \ +\\arc (-1) .. controls (1.4666666666666668, 1.0833333333333335) and (1.2, 1.08\ +33333333333335) .. (-3);\n \\arc (-1) .. controls (1.0666666666666667, 0.6666\ +6666666666674) and (0.93333333333333324, 0.66666666666666674) .. (-2);\n \\ar\ +c (-1) edge [botloop] (-1);\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \\a\ +rc (-1) to (3);\n\n % arcs from vertex 2\n \\arc (2) to (-3);\n \\arc (2) t\ +o (-2);\n \\arc (2) to (-1);\n \\arc (2) .. controls (0.93333333333333324, 2\ +.3333333333333335) and (1.0666666666666667, 2.3333333333333335) .. (1);\n \\a\ +rc (2) edge [toploop] (2);\n \\arc (2) .. controls (1.7333333333333334, 2.333\ +3333333333335) and (1.6000000000000001, 2.3333333333333335) .. (3);\n\n % arc\ +s from vertex -2\n \\arc (-2) .. controls (1.7333333333333334, 0.666666666666\ +66674) and (1.6000000000000001, 0.66666666666666674) .. (-3);\n \\arc (-2) ed\ +ge [botloop] (-2);\n \\arc (-2) .. controls (0.93333333333333324, 0.666666666\ +66666674) and (1.0666666666666667, 0.66666666666666674) .. (-1);\n \\arc (-2)\ + to (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from vertex 3\ +\n \\arc (3) to (-3);\n \\arc (3) to (-2);\n \\arc (3) to (-1);\n \\arc (3\ +) .. controls (1.2, 1.9166666666666665) and (1.4666666666666668, 1.91666666666\ +66665) .. (1);\n \\arc (3) .. controls (1.6000000000000001, 2.333333333333333\ +5) and (1.7333333333333334, 2.3333333333333335) .. (2);\n \\arc (3) edge [top\ +loop] (3);\n\n % arcs from vertex -3\n \\arc (-3) edge [botloop] (-3);\n \\\ +arc (-3) .. controls (1.6000000000000001, 0.66666666666666674) and (1.73333333\ +33333334, 0.66666666666666674) .. (-2);\n \\arc (-3) .. controls (1.2, 1.0833\ +333333333335) and (1.4666666666666668, 1.0833333333333335) .. (-1);\n \\arc (\ +-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\ +\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw\ +, fill=black, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner \ +sep = 0.14cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n\ + toploop/.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and\ + labels\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {\ +};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1\ +,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) \ +at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edge [toploop]\ + (1);\n\n % arcs from vertex -1\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n\ + \\arc (-1) to (3);\n\n % arcs from vertex 2\n\n % arcs from vertex -2\n \ +\\arc (-2) edge [botloop] (-2);\n \\arc (-2) to (1);\n \\arc (-2) to (2);\n \ + \\arc (-2) to (3);\n\n % arcs from vertex 3\n\n % arcs from vertex -3\n \\\ +arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpict\ +ure}\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, \ +draw, fill=black, inner sep =0.04cm},\n ghost/.style={circle, draw = none, in\ +ner sep = 0.14cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110\ +},\n toploop/.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices\ + and labels\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, \ +3) {};\n \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i i\ +n {1,...,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\ +\\i) at (\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) .. contro\ +ls (1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, 2.333333\ +3333333335) .. (2);\n\n % arcs from vertex -1\n \\arc (-1) .. controls (1.46\ +66666666666668, 1.0833333333333335) and (1.2, 1.0833333333333335) .. (-3);\n \ +\\arc (-1) .. controls (1.0666666666666667, 0.66666666666666674) and (0.933333\ +33333333324, 0.66666666666666674) .. (-2);\n \\arc (-1) edge [botloop] (-1);\ +\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) to (3);\n\n % arcs\ + from vertex 2\n \\arc (2) .. controls (0.93333333333333324, 2.33333333333333\ +35) and (1.0666666666666667, 2.3333333333333335) .. (1);\n \\arc (2) edge [to\ +ploop] (2);\n \\arc (2) .. controls (1.7333333333333334, 2.3333333333333335) \ +and (1.6000000000000001, 2.3333333333333335) .. (3);\n\n % arcs from vertex -\ +2\n \\arc (-2) .. controls (1.7333333333333334, 0.66666666666666674) and (1.6\ +000000000000001, 0.66666666666666674) .. (-3);\n \\arc (-2) edge [botloop] (-\ +2);\n \\arc (-2) .. controls (0.93333333333333324, 0.66666666666666674) and (\ +1.0666666666666667, 0.66666666666666674) .. (-1);\n \\arc (-2) to (1);\n \\a\ +rc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from vertex 3\n \\arc (3) .\ +. controls (1.2, 1.9166666666666665) and (1.4666666666666668, 1.91666666666666\ +65) .. (1);\n \\arc (3) .. controls (1.6000000000000001, 2.3333333333333335) \ +and (1.7333333333333334, 2.3333333333333335) .. (2);\n \\arc (3) edge [toploo\ +p] (3);\n\n % arcs from vertex -3\n \\arc (-3) edge [botloop] (-3);\n \\arc\ + (-3) .. controls (1.6000000000000001, 0.66666666666666674) and (1.73333333333\ +33334, 0.66666666666666674) .. (-2);\n \\arc (-3) .. controls (1.2, 1.0833333\ +333333335) and (1.4666666666666668, 1.0833333333333335) .. (-1);\n \\arc (-3)\ + to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\ +\\bigskip\\bigskip\n\n\\begin{tikzpicture}[\n vertex/.style={circle, draw, fi\ +ll=black, inner sep =0.04cm},\n ghost/.style={circle, draw = none, inner sep \ += 0.14cm},\n botloop/.style={min distance = 8mm, out = -70, in = -110},\n to\ +ploop/.style={min distance = 8mm, out = 70, in = 110}]\n\n % vertices and lab\ +els\n \\foreach \\i in {1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n\ + \\node [ghost] (\\i) at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...\ +,3} {\n \\node [vertex] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\ +\\i/1.5, 0) {};\n }\n\n % arcs from vertex 1\n \\arc (1) edge [toploop] (1)\ +;\n \\arc (1) .. controls (1.0666666666666667, 2.3333333333333335) and (0.933\ +33333333333324, 2.3333333333333335) .. (2);\n \\arc (1) .. controls (1.466666\ +6666666668, 1.9166666666666665) and (1.2, 1.9166666666666665) .. (3);\n\n % a\ +rcs from vertex -1\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc (-1) t\ +o (3);\n\n % arcs from vertex 2\n \\arc (2) .. controls (0.93333333333333324\ +, 2.3333333333333335) and (1.0666666666666667, 2.3333333333333335) .. (1);\n \ +\\arc (2) edge [toploop] (2);\n \\arc (2) .. controls (1.7333333333333334, 2.\ +3333333333333335) and (1.6000000000000001, 2.3333333333333335) .. (3);\n\n % \ +arcs from vertex -2\n \\arc (-2) edge [botloop] (-2);\n \\arc (-2) to (1);\n\ + \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs from vertex 3\n \\arc \ +(3) .. controls (1.2, 1.9166666666666665) and (1.4666666666666668, 1.916666666\ +6666665) .. (1);\n \\arc (3) .. controls (1.6000000000000001, 2.3333333333333\ +335) and (1.7333333333333334, 2.3333333333333335) .. (2);\n \\arc (3) edge [t\ +oploop] (3);\n\n % arcs from vertex -3\n \\arc (-3) to (1);\n \\arc (-3) to\ + (2);\n \\arc (-3) to (3);\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\b\ +egin{tikzpicture}[\n vertex/.style={circle, draw, fill=black, inner sep =0.04\ +cm},\n ghost/.style={circle, draw = none, inner sep = 0.14cm},\n botloop/.st\ +yle={min distance = 8mm, out = -70, in = -110},\n toploop/.style={min distanc\ +e = 8mm, out = 70, in = 110}]\n\n % vertices and labels\n \\foreach \\i in {\ +1,...,3} {\n \\node [vertex] at (\\i/1.5, 3) {};\n \\node [ghost] (\\i) \ +at (\\i/1.5, 3) {};\n }\n\n \\foreach \\i in {1,...,3} {\n \\node [vertex\ +] at (\\i/1.5, 0) {};\n \\node [ghost] (-\\i) at (\\i/1.5, 0) {};\n }\n\n \ + % arcs from vertex 1\n \\arc (1) edge [toploop] (1);\n \\arc (1) .. control\ +s (1.0666666666666667, 2.3333333333333335) and (0.93333333333333324, 2.3333333\ +333333335) .. (2);\n \\arc (1) .. controls (1.4666666666666668, 1.91666666666\ +66665) and (1.2, 1.9166666666666665) .. (3);\n\n % arcs from vertex -1\n \\a\ +rc (-1) .. controls (1.4666666666666668, 1.0833333333333335) and (1.2, 1.08333\ +33333333335) .. (-3);\n \\arc (-1) .. controls (1.0666666666666667, 0.6666666\ +6666666674) and (0.93333333333333324, 0.66666666666666674) .. (-2);\n \\arc (\ +-1) edge [botloop] (-1);\n \\arc (-1) to (1);\n \\arc (-1) to (2);\n \\arc \ +(-1) to (3);\n\n % arcs from vertex 2\n \\arc (2) .. controls (0.93333333333\ +333324, 2.3333333333333335) and (1.0666666666666667, 2.3333333333333335) .. (1\ +);\n \\arc (2) edge [toploop] (2);\n \\arc (2) .. controls (1.73333333333333\ +34, 2.3333333333333335) and (1.6000000000000001, 2.3333333333333335) .. (3);\n\ +\n % arcs from vertex -2\n \\arc (-2) .. controls (1.7333333333333334, 0.666\ +66666666666674) and (1.6000000000000001, 0.66666666666666674) .. (-3);\n \\ar\ +c (-2) edge [botloop] (-2);\n \\arc (-2) .. controls (0.93333333333333324, 0.\ +66666666666666674) and (1.0666666666666667, 0.66666666666666674) .. (-1);\n \ +\\arc (-2) to (1);\n \\arc (-2) to (2);\n \\arc (-2) to (3);\n\n % arcs fro\ +m vertex 3\n \\arc (3) .. controls (1.2, 1.9166666666666665) and (1.466666666\ +6666668, 1.9166666666666665) .. (1);\n \\arc (3) .. controls (1.6000000000000\ +001, 2.3333333333333335) and (1.7333333333333334, 2.3333333333333335) .. (2);\ +\n \\arc (3) edge [toploop] (3);\n\n % arcs from vertex -3\n \\arc (-3) edg\ +e [botloop] (-3);\n \\arc (-3) .. controls (1.6000000000000001, 0.66666666666\ +666674) and (1.7333333333333334, 0.66666666666666674) .. (-2);\n \\arc (-3) .\ +. controls (1.2, 1.0833333333333335) and (1.4666666666666668, 1.08333333333333\ +35) .. (-1);\n \\arc (-3) to (1);\n \\arc (-3) to (2);\n \\arc (-3) to (3);\ +\n\n\\end{tikzpicture}\n\n\\bigskip\\bigskip\n\n\\end{center}\\end{document}" # TikzString for a bipartition collection gap> TikzString(PartitionMonoid(2)); -"1\n2\n3\n4\n5\n\\begin{center}\n\\begin{tikzpicture}\n\n %block number 1\n \ -%vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.9499999999999999\ -6, 2.2) node [above] {$1$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) no\ -de [below] {$-1$};\n\n %lines\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n\ - %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node \ -[above] {$2$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$\ --2$};\n\n %lines\n \\draw(2, 2)--(2, 0);\n\\end{tikzpicture}\n\n\n\\bigskip\ -\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and labels\ +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\n\\begin{document}\\be\ +gin{center}\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and labels\ \n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [above]\ - {$1$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\ -\n %lines\n \\draw(1, 2)--(2, 0);\n\n %block number 2\n %vertices and labe\ + {$1$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\ +\n %lines\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n %vertices and labe\ ls\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\\ -fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n \ - \\draw(2, 2)--(1, 0);\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{\ +fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \ + \\draw(2, 2)--(2, 0);\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{\ tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)circl\ -e(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\ -\n %block number 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\\ -draw(1.95, 2.2) node [above] {$2$};\n \\fill(2, 0)circle(.125);\n \\draw(2, \ --0.2) node [below] {$-2$};\n\n %lines\n \\draw(2, 2)--(2, 0);\n\n %block nu\ -mber 3\n %vertices and labels\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2)\ - node [below] {$-1$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\ -\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fil\ -l(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n\ - \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill\ -(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)cir\ -cle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 1.\ -875) .. controls (1, 1.25) and (2, 1.25) .. (2, 1.875);\n \\draw(1, 0.125) ..\ - controls (1, 0.75) and (2, 0.75) .. (2, 0.125);\n \\draw(1, 2)--(1, 0);\n\\e\ +e(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \\fill(2, \ +0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(\ +1, 2)--(2, 0);\n\n %block number 2\n %vertices and labels\n \\fill(2, 2)cir\ +cle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill(1, 0)circle(.125\ +);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n \\draw(2, 2)--(1, 0)\ +;\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %bl\ +ock number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.\ +94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %block number 2\n\ + %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node \ +[above] {$2$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$\ +-2$};\n\n %lines\n \\draw(2, 2)--(2, 0);\n\n %block number 3\n %vertices a\ +nd labels\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\ +\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpictur\ +e}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n\ + \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \\fill(2, 2)circle(.\ +125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill(1, 0)circle(.125);\n \ + \\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle(.125);\n \\draw(2\ +, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 1.875) .. controls (1, 1\ +.25) and (2, 1.25) .. (2, 1.875);\n \\draw(1, 0.125) .. controls (1, 0.75) an\ +d (2, 0.75) .. (2, 0.125);\n \\draw(1, 2)--(1, 0);\n\\end{tikzpicture}\n\n\n\ +\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices a\ +nd labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) nod\ +e [above] {$1$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] \ +{$-2$};\n\n %lines\n \\draw(1, 2)--(2, 0);\n\n %block number 2\n %vertices\ + and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2\ +$};\n\n %lines\n\n %block number 3\n %vertices and labels\n \\fill(1, 0)ci\ +rcle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n\\end{tikzpic\ +ture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n \ +%vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.9499999999999999\ +6, 2.2) node [above] {$1$};\n\n %lines\n\n %block number 2\n %vertices and \ +labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n\ + \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %line\ +s\n \\draw(2, 2)--(1, 0);\n\n %block number 3\n %vertices and labels\n \\f\ +ill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\\ +end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block n\ +umber 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999\ +999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %block number 2\n %ve\ +rtices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [abov\ +e] {$2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\ +\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %li\ +nes\n \\draw(1, 0.125) .. controls (1, 0.75) and (2, 0.75) .. (2, 0.125);\n \ +\\draw(2, 2)--(2, 0);\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{t\ +ikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)circle\ +(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \\fill(2, 2\ +)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill(2, 0)circle(\ +.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 1.875)\ + .. controls (1, 1.25) and (2, 1.25) .. (2, 1.875);\n \\draw(2, 2)--(2, 0);\n\ +\n %block number 2\n %vertices and labels\n \\fill(1, 0)circle(.125);\n \\\ +draw(1, -0.2) node [below] {$-1$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigs\ +kip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and lab\ +els\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [abo\ +ve] {$1$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$}\ +;\n\n %lines\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n %vertices and l\ +abels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n\ +\n %lines\n\n %block number 3\n %vertices and labels\n \\fill(2, 0)circle(\ +.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\end{tikzpicture}\ +\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vert\ +ices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.\ +2) node [above] {$1$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [b\ +elow] {$-1$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-\ +2$};\n\n %lines\n \\draw(1, 0.125) .. controls (1, 0.75) and (2, 0.75) .. (2\ +, 0.125);\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n %vertices and label\ +s\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n\n %\ +lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n \ + %block number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\dra\ +w(0.94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %block number\ + 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) n\ +ode [above] {$2$};\n\n %lines\n\n %block number 3\n %vertices and labels\n \ + \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\ +\n\n %block number 4\n %vertices and labels\n \\fill(2, 0)circle(.125);\n \ +\\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bi\ +gskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and l\ +abels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [a\ +bove] {$1$};\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$\ +2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n \ + %lines\n \\draw(1, 1.875) .. controls (1, 1.25) and (2, 1.25) .. (2, 1.875);\ +\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n %vertices and labels\n \\fi\ +ll(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\e\ nd{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block nu\ mber 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.949999\ -99999999996, 2.2) node [above] {$1$};\n \\fill(2, 0)circle(.125);\n \\draw(2\ -, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 2)--(2, 0);\n\n %block \ -number 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, \ -2.2) node [above] {$2$};\n\n %lines\n\n %block number 3\n %vertices and lab\ -els\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n \ -%lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n\ - %block number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\dr\ -aw(0.94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %block numbe\ -r 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) \ -node [above] {$2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [belo\ -w] {$-1$};\n\n %lines\n \\draw(2, 2)--(1, 0);\n\n %block number 3\n %verti\ -ces and labels\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$\ --2$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzp\ -icture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)circle(.12\ -5);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %\ -block number 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(\ -1.95, 2.2) node [above] {$2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2)\ - node [below] {$-1$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [be\ -low] {$-2$};\n\n %lines\n \\draw(1, 0.125) .. controls (1, 0.75) and (2, 0.7\ -5) .. (2, 0.125);\n \\draw(2, 2)--(2, 0);\n\\end{tikzpicture}\n\n\n\\bigskip\ -\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and labels\ -\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [above]\ - {$1$};\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\ -\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %li\ -nes\n \\draw(1, 1.875) .. controls (1, 1.25) and (2, 1.25) .. (2, 1.875);\n \ -\\draw(2, 2)--(2, 0);\n\n %block number 2\n %vertices and labels\n \\fill(1\ -, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n\\end{t\ -ikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number\ - 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.9499999999\ -9999996, 2.2) node [above] {$1$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0\ -.2) node [below] {$-1$};\n\n %lines\n \\draw(1, 2)--(1, 0);\n\n %block numb\ -er 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2)\ - node [above] {$2$};\n\n %lines\n\n %block number 3\n %vertices and labels\ -\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %li\ -nes\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %\ -block number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(\ -0.94999999999999996, 2.2) node [above] {$1$};\n \\fill(1, 0)circle(.125);\n \ -\\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle(.125);\n \\draw(2,\ - -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 0.125) .. controls (1, 0.\ -75) and (2, 0.75) .. (2, 0.125);\n \\draw(1, 2)--(1, 0);\n\n %block number 2\ -\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) nod\ -e [above] {$2$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\\ -begin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2\ -)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n\n %l\ -ines\n\n %block number 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\ -\n \\draw(1.95, 2.2) node [above] {$2$};\n\n %lines\n\n %block number 3\n \ -%vertices and labels\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [bel\ -ow] {$-1$};\n\n %lines\n\n %block number 4\n %vertices and labels\n \\fill\ -(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\end\ -{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block numb\ -er 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999\ -999999996, 2.2) node [above] {$1$};\n \\fill(2, 2)circle(.125);\n \\draw(1.9\ -5, 2.2) node [above] {$2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) no\ -de [below] {$-1$};\n\n %lines\n \\draw(1, 1.875) .. controls (1, 1.25) and (\ -2, 1.25) .. (2, 1.875);\n \\draw(1, 2)--(1, 0);\n\n %block number 2\n %vert\ -ices and labels\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {\ -$-2$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikz\ -picture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)circle(.1\ -25);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n\n %lines\n\n \ -%block number 2\n %vertices and labels\n \\fill(2, 2)circle(.125);\n \\draw\ -(1.95, 2.2) node [above] {$2$};\n\n %lines\n\n %block number 3\n %vertices \ -and labels\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$}\ -;\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %l\ -ines\n \\draw(1, 0.125) .. controls (1, 0.75) and (2, 0.75) .. (2, 0.125);\n\ -\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block\ - number 1\n %vertices and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.949\ -99999999999996, 2.2) node [above] {$1$};\n \\fill(2, 2)circle(.125);\n \\dra\ -w(1.95, 2.2) node [above] {$2$};\n\n %lines\n \\draw(1, 1.875) .. controls (\ -1, 1.25) and (2, 1.25) .. (2, 1.875);\n\n %block number 2\n %vertices and la\ -bels\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n \ - %lines\n\n %block number 3\n %vertices and labels\n \\fill(2, 0)circle(.12\ -5);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n\\end{tikzpicture}\n\ -\n\n\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertic\ -es and labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2)\ - node [above] {$1$};\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [a\ -bove] {$2$};\n\n %lines\n \\draw(1, 1.875) .. controls (1, 1.25) and (2, 1.2\ -5) .. (2, 1.875);\n\n %block number 2\n %vertices and labels\n \\fill(1, 0)\ -circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle(.1\ -25);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 0.125) .\ -. controls (1, 0.75) and (2, 0.75) .. (2, 0.125);\n\\end{tikzpicture}\n\n\n\\b\ -igskip\\bigskip\n\n\\end{center}\\end{document}" +99999999996, 2.2) node [above] {$1$};\n\n %lines\n\n %block number 2\n %ver\ +tices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above\ +] {$2$};\n\n %lines\n\n %block number 3\n %vertices and labels\n \\fill(1,\ + 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle\ +(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n\n %lines\n \\draw(1, 0.125\ +) .. controls (1, 0.75) and (2, 0.75) .. (2, 0.125);\n\\end{tikzpicture}\n\n\n\ +\\bigskip\\bigskip\n\n\\begin{tikzpicture}\n\n %block number 1\n %vertices a\ +nd labels\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) nod\ +e [above] {$1$};\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above\ +] {$2$};\n\n %lines\n \\draw(1, 1.875) .. controls (1, 1.25) and (2, 1.25) .\ +. (2, 1.875);\n\n %block number 2\n %vertices and labels\n \\fill(1, 0)circ\ +le(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n\n %block numb\ +er 3\n %vertices and labels\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) n\ +ode [below] {$-2$};\n\n %lines\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\ +\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(\ +1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \ +\\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n\n %lines\ +\n \\draw(1, 1.875) .. controls (1, 1.25) and (2, 1.25) .. (2, 1.875);\n\n %\ +block number 2\n %vertices and labels\n \\fill(1, 0)circle(.125);\n \\draw(\ +1, -0.2) node [below] {$-1$};\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) \ +node [below] {$-2$};\n\n %lines\n \\draw(1, 0.125) .. controls (1, 0.75) and\ + (2, 0.75) .. (2, 0.125);\n\\end{tikzpicture}\n\n\n\\bigskip\\bigskip\n\n\\end\ +{center}\\end{document}" # Test TikzString for a bipartition gap> TikzString(Bipartition([[1, 3], [2, -1], [-2, -3]])); -"1\n2\n3\n4\n5\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and lab\ -els\n \\fill(1, 2)circle(.125);\n \\draw(0.94999999999999996, 2.2) node [abo\ -ve] {$1$};\n \\fill(3, 2)circle(.125);\n \\draw(2.9500000000000002, 2.2) nod\ -e [above] {$3$};\n\n %lines\n \\draw(1, 1.875) .. controls (1, 1.16666666666\ -66667) and (3, 1.1666666666666667) .. (3, 1.875);\n\n %block number 2\n %ver\ -tices and labels\n \\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above\ -] {$2$};\n \\fill(1, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\ -\n\n %lines\n \\draw(2, 2)--(1, 0);\n\n %block number 3\n %vertices and la\ -bels\n \\fill(2, 0)circle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n \ -\\fill(3, 0)circle(.125);\n \\draw(3, -0.2) node [below] {$-3$};\n\n %lines\ -\n \\draw(2, 0.125) .. controls (2, 0.66666666666666663) and (3, 0.6666666666\ -6666663) .. (3, 0.125);\n\\end{tikzpicture}\n\n\\end{document}" -gap> TikzString(Bipartition([[1, 3], [2, -1], [-2, -3]]), -> rec(colors := true, labels := true, beginDocument := true, +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\n\\begin{document}\\be\ +gin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill(1, 2)c\ +ircle(.125);\n \\draw(0.94999999999999996, 2.2) node [above] {$1$};\n \\fill\ +(3, 2)circle(.125);\n \\draw(2.9500000000000002, 2.2) node [above] {$3$};\n\n\ + %lines\n \\draw(1, 1.875) .. controls (1, 1.1666666666666667) and (3, 1.166\ +6666666666667) .. (3, 1.875);\n\n %block number 2\n %vertices and labels\n \ +\\fill(2, 2)circle(.125);\n \\draw(1.95, 2.2) node [above] {$2$};\n \\fill(1\ +, 0)circle(.125);\n \\draw(1, -0.2) node [below] {$-1$};\n\n %lines\n \\dra\ +w(2, 2)--(1, 0);\n\n %block number 3\n %vertices and labels\n \\fill(2, 0)c\ +ircle(.125);\n \\draw(2, -0.2) node [below] {$-2$};\n \\fill(3, 0)circle(.12\ +5);\n \\draw(3, -0.2) node [below] {$-3$};\n\n %lines\n \\draw(2, 0.125) ..\ + controls (2, 0.66666666666666663) and (3, 0.66666666666666663) .. (3, 0.125);\ +\n\\end{tikzpicture}\n\n\\end{document}" +gap> TikzString(Bipartition([[1, 3], [2, -1], [-2, -3]]), +> rec(colors := true, labels := true, beginDocument := true, > endDocument := true)); -"1\n2\n3\n4\n5\n\\begin{tikzpicture}\n\n %block number 1\n %vertices and lab\ -els\n \\fill[red](1, 2)circle(.125);\n \\draw[red](0.94999999999999996, 2.2)\ - node [above] {$1$};\n \\fill[red](3, 2)circle(.125);\n \\draw[red](2.950000\ -0000000002, 2.2) node [above] {$3$};\n\n %lines\n \\draw[red](1, 1.875) .. c\ -ontrols (1, 1.1666666666666667) and (3, 1.1666666666666667) .. (3, 1.875);\n\n\ - %block number 2\n %vertices and labels\n \\fill[green](2, 2)circle(.125);\ -\n \\draw[green](1.95, 2.2) node [above] {$2$};\n \\fill[green](1, 0)circle(\ -.125);\n \\draw[green](1, -0.2) node [below] {$-1$};\n\n %lines\n \\draw[gr\ -een](2, 2)--(1, 0);\n\n %block number 3\n %vertices and labels\n \\fill[blu\ -e](2, 0)circle(.125);\n \\draw[blue](2, -0.2) node [below] {$-2$};\n \\fill[\ -blue](3, 0)circle(.125);\n \\draw[blue](3, -0.2) node [below] {$-3$};\n\n %l\ -ines\n \\draw[blue](2, 0.125) .. controls (2, 0.66666666666666663) and (3, 0.\ -66666666666666663) .. (3, 0.125);\n\\end{tikzpicture}\n\n\\end{document}" +"%latex\n\\documentclass{minimal}\n\\usepackage{tikz}\n\n\\begin{document}\\be\ +gin{tikzpicture}\n\n %block number 1\n %vertices and labels\n \\fill[red](1\ +, 2)circle(.125);\n \\draw[red](0.94999999999999996, 2.2) node [above] {$1$};\ +\n \\fill[red](3, 2)circle(.125);\n \\draw[red](2.9500000000000002, 2.2) nod\ +e [above] {$3$};\n\n %lines\n \\draw[red](1, 1.875) .. controls (1, 1.166666\ +6666666667) and (3, 1.1666666666666667) .. (3, 1.875);\n\n %block number 2\n \ + %vertices and labels\n \\fill[green](2, 2)circle(.125);\n \\draw[green](1.9\ +5, 2.2) node [above] {$2$};\n \\fill[green](1, 0)circle(.125);\n \\draw[gree\ +n](1, -0.2) node [below] {$-1$};\n\n %lines\n \\draw[green](2, 2)--(1, 0);\n\ +\n %block number 3\n %vertices and labels\n \\fill[blue](2, 0)circle(.125);\ +\n \\draw[blue](2, -0.2) node [below] {$-2$};\n \\fill[blue](3, 0)circle(.12\ +5);\n \\draw[blue](3, -0.2) node [below] {$-3$};\n\n %lines\n \\draw[blue](\ +2, 0.125) .. controls (2, 0.66666666666666663) and (3, 0.66666666666666663) ..\ + (3, 0.125);\n\\end{tikzpicture}\n\n\\end{document}" # Test DotString for a semigroup -gap> DotString(RegularBooleanMatMonoid(3)); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\ -\n
1
*
>];\n2 [shape=box style=invisible label=<\n\n\ -\n\n\n\n<\ -TD BGCOLOR=\"white\">\n\n<\ -TR>\n
2
******\ -*
******
******
******
****
****
*\ -***
>];\n3 [shape=box style=inv\ -isible label=<\n\n\ -\n\n\n\n\n\n\n\n\n\ -\n<\ -TD BGCOLOR=\"gray\">*\n*\n
\ -3
*****
***
***
***
***
\ -***
\ -*****
*\ -**
**<\ -/TD>***
***
**
**
>];\n4 [sha\ -pe=box style=invisible label=<\n\n\n<\ -TD BGCOLOR=\"white\">\n\n<\ -TR>\n<\ -TD BGCOLOR=\"white\">\n\n
4
*
*
*
*
*
*
>];\n5 [shape=box st\ -yle=invisible label=<\n\n*\ -\n\n\n<\ -TR>\n<\ -TD BGCOLOR=\"white\">\n\n\ -\n\n\n
5
***
***
***
*
****\ -
****
***
*
\ -*
>];\n6 [shape=box style=invi\ -sible label=<\n\n\n\ -\n<\ -/TR>\n\ -\n<\ -TD CELLPADDING=\"10\" BGCOLOR=\"white\">*\n\ -*\n
6<\ -/TD>
*<\ -/font>***\ -**
****<\ -/TD>**
***\ -***
***<\ -/TD>***
**\ -***
**<\ -/TD>***
>];\n7 [shape=box style=invisible label=<\n\n\n\n<\ -TR>\n
7
*
*
\ -*
>];\n8 [shape=box style=invisible label=<\n\n\n\n\n
8
*
*
*
>];\n9 [shape=box style=invisible label=<\n\n 9*\ -\n*\n\ -*\n*\n*\n\ -*\n>];\n10 [shape=box style=invisible label=<\n\n\ -\n
10
*
>];\n2 -> 1\n3 -> 2\n4 -> 3\n5 -> 3\n6 -> 4\n6\ - -> 5\n7 -> 4\n7 -> 5\n8 -> 4\n8 -> 5\n9 -> 6\n9 -> 7\n9 -> 8\n10 -> 9\n }" +gap> GraphvizDClasses(RegularBooleanMatMonoid(3)); + gap> DotString(RegularBooleanMatMonoid(2), rec(maximal := true)); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\ -\n
1
1
>];\n2 [shape=box style=invisible label=<\n\n\ -\n\n\n
2
111
11
11\ -
>];\n3 [shape=box style=invisible label=<\n\n\n1\n
3
1
>];\n4 [shape=box style=invisible labe\ -l=<\n\n<\ -TR>\n
4
C2
>];\n2 -> 1\n3 -> 2\n4 -> 3\n }" +"//dot\ndigraph DClasses {\n\tnode [shape=plaintext] edge [color=black, arrowh\ +ead=none] \n\t1 [label=<\n<\ +/TR>\n
1
1
>, shape=box, style=invisible]\n\t2 [label=<\n\n<\ +TD BGCOLOR=\"gray\">1\n\n
2
111
<\ +font color=\"white\">*1\ +
*11
>, shape=box, style=invisib\ +le]\n\t3 [label=<\n\n\n
3<\ +/TD>
1*
*1
>, shape=box, style=invisible]\n\t4 [label=<\n4C2\n>, shape=box,\ + style=invisible]\n\t2 -> 1\n\t3 -> 2\n\t4 -> 3\n}\n" gap> DotString(RegularBooleanMatMonoid(2), rec(number := false)); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\n
*
>];\n2 [shape=box style=invisible label=<\n\n<\ -TR>\n\n\n
**\ -*
**
**
>];\n3 [shape=box style=invis\ -ible label=<\n\n\n\n>];\n4 [shape=box style=invisible label=<\n
*
*
\n\n
*
>];\n2 -> 1\n3 -> 2\n4 -> 3\n }" +"//dot\ndigraph DClasses {\n\tnode [shape=plaintext] edge [color=black, arrowh\ +ead=none] \n\t1 [label=<\n\n
*
>, shape=box, style=invisible]\n\t2 [label=<\n***\n*\ +**\n***\ +\n>, shape=box, style=invisible]\n\t3 [label=<\n\n\n<\ +/TABLE>>, shape=box, style=invisible]\n\t4 [label=<
**
**
\n\n
*
>, shape=box, style=i\ +nvisible]\n\t2 -> 1\n\t3 -> 2\n\t4 -> 3\n}\n" gap> DotString(RegularBooleanMatMonoid(2), rec(normal := false)); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\ -\n
1
*
>];\n2 [shape=box style=invisible label=<\n\n\ -\n\n\n
2
**
**
***\ -
>];\n3 [shape=box style=invisible label=<\n\n\n*\n
3
*
>];\n4 [shape=box style=invisible labe\ -l=<\n\n<\ -TR>\n
4
*
>];\n2 -> 1\n3 -> 2\n4 -> 3\n }" +"//dot\ndigraph DClasses {\n\tnode [shape=plaintext] edge [color=black, arrowh\ +ead=none] \n\t1 [label=<\n<\ +/TR>\n
1
*
>, shape=box, style=invisible]\n\t2 [label=<\n\n\ +\n\n
2
**<\ +/font>*
*\ +*\ +*
***
>, shape=box, style=invisib\ +le]\n\t3 [label=<\n\n\n
3<\ +/TD>
**
**
>, shape=box, style=invisible]\n\t4 [label=<\n4*\n>, shape=box, \ +style=invisible]\n\t2 -> 1\n\t3 -> 2\n\t4 -> 3\n}\n" gap> S := RegularBooleanMatMonoid(3);; -gap> DotString(S, rec(highlight := [rec(HClasses := [HClass(S, One(S))]), +gap> GraphvizDClasses(S, rec(highlight := [rec(HClasses := [HClass(S, One(S))]), > rec(HClasses := [First(HClasses(S), x -> not IsGroupHClass(x))]), > rec(HClasses := HClasses(First(DClasses(S), x -> not IsRegularDClass(x)))) > ])); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\ -\n
1
*
>];\n2 [shape=box style=invisible label=<\n\n\ -\n\n\n\n<\ -TD BGCOLOR=\"white\">\n\n<\ -TR>\n
2
******\ -*
******
******
******
****
****
****
>];\n3 [shape=box style=\ -invisible label=<\n\n\ -\n<\ -TD BGCOLOR=\"white\">\n\n\n\n\n\n\n\n\ -\n<\ -TD BGCOLOR=\"gray\">*\n*\n
3
*****
***
***
***
***
\ -***
\ -*****
*\ -**
**<\ -/TD>***
***
**
**
>];\n4 [sha\ -pe=box style=invisible label=<\n\n\n<\ -TD BGCOLOR=\"white\">\n\n<\ -TR>\n<\ -TD BGCOLOR=\"white\">\n\n
4
*
*
*
*
*
*
>];\n5 [shape=box st\ -yle=invisible label=<\n\n*\ -\n\n\n<\ -TR>\n<\ -TD BGCOLOR=\"white\">\n\n\ -\n\n\n
5
***
***
***
*
****\ -
****
***
*
\ -*
>];\n6 [shape=box style=invi\ -sible label=<\n\n\n\n\n\n\n\n>];\n7 [shape=box style=invisible label=<\n
6<\ -/TD>
\ -*\ -*\ -*\ -*\ -*\ -*
******
\ -*\ -*\ -*\ -*\ -*\ -*
******
******
******
\n 7\n\n\ -\n
*
*
*
>];\n8 [shape=box style=invisible label=<\n\n\n\ -\n\n
8
*\ -
*
*
>];\n9 [shape=box style=invisible label=<\n\n\ -\n\n<\ -TD BGCOLOR=\"gray\">*\n\n\n<\ -TD BGCOLOR=\"white\">\n
9
*
*
*
*
*
>];\n10 [shape=box style=invisible label=<\n\n\n
10
*
>];\n2 -> 1\n3 -> 2\n4 -> 3\n5 -> 3\n6 -> 4\n6 -> \ -5\n7 -> 4\n7 -> 5\n8 -> 4\n8 -> 5\n9 -> 6\n9 -> 7\n9 -> 8\n10 -> 9\n }" + # DotString with option idempotentsemilattice gap> S := Semigroup(SymmetricInverseMonoid(3), rec(acting := true));; gap> DotString(S, rec(idempotentsemilattice := true)); -"//dot\ndigraph DClasses {\nnode [shape=plaintext]\nedge [color=black,arrowhe\ -ad=none]\n1 [shape=box style=invisible label=<\n\n\n
1
*
>];\n2 [shape=box style=invisible label=<\n\n\ -\n<\ -TD BGCOLOR=\"white\">\n\n
2
*
*
*
>];\n3 [sha\ -pe=box style=invisible label=<\n\n\n\n\ -\n
3
*
\ -*
*
>];\n4 [shape=box style=invisible label=<\n<\ -TABLE BORDER=\"0\" CELLBORDER=\"1\" CELLPADDING=\"10\" CELLSPACING=\"0\" PORT=\ -\"4\">\n 4*\n>];\n1 -> 2\n2 -> 3\n3 -> 4\ -\nedge [color=blue,arrowhead=none,style=dashed]\n3:e2 -> 4:e1\n3:e3 -> 4:e1\n2\ -:e4 -> 3:e2\n2:e4 -> 3:e3\n3:e5 -> 4:e1\n2:e6 -> 3:e3\n2:e6 -> 3:e5\n2:e7 -> 3\ -:e2\n2:e7 -> 3:e5\n1:e8 -> 2:e4\n1:e8 -> 2:e6\n1:e8 -> 2:e7\n }" +"//dot\ndigraph DClasses {\n\tnode [shape=plaintext] edge [color=black, arrowh\ +ead=none] \n\t1 [label=<\n<\ +/TR>\n
1
*
>, shape=box, style=invisible]\n\t2 [label=<\n\n\n\n
2
**<\ +/font>*
***
***
>, shape=box, style=in\ +visible]\n\t3 [label=<\n\n\n\n
3
***
***
***\ +
>, shape=box, style=invisible]\n\t4 [label=<\n\n
4
*
>, shape=box, style=invis\ +ible]\n\t1 -> 2\n\t2 -> 3\n\t3 -> 4\n}\n" # DotSemilatticeOfIdempotents gap> S := Semigroup(SymmetricInverseMonoid(3), rec(acting := true));; gap> DotSemilatticeOfIdempotents(S); -"//dot\ngraph graphname {\n node [shape=point]\nranksep=2;\nsubgraph cluster_\ -1{\n8 \n}\nsubgraph cluster_2{\n6 4 7 \n}\nsubgraph cluster_3{\n3 5 2 \n}\nsub\ -graph cluster_4{\n1 \n}\n2 -- 1\n3 -- 1\n4 -- 2\n4 -- 3\n5 -- 1\n6 -- 3\n6 -- \ -5\n7 -- 2\n7 -- 5\n8 -- 4\n8 -- 6\n8 -- 7\n }" +"//dot\ngraph semilattice {\n\tnode[shape=point] ranksep=2 \nsubgraph cluster_\ +1 {\n\t8\n}\nsubgraph cluster_2 {\n\t6\n\t4\n\t7\n}\nsubgraph cluster_3 {\n\t3\ +\n\t5\n\t2\n}\nsubgraph cluster_4 {\n\t1\n}\n\t2 -- 1\n\t3 -- 1\n\t4 -- 2\n\t4\ + -- 3\n\t5 -- 1\n\t6 -- 3\n\t6 -- 5\n\t7 -- 2\n\t7 -- 5\n\t8 -- 4\n\t8 -- 7\n\ +\t8 -- 6\n}\n" gap> S := Semigroup(SymmetricInverseMonoid(3), rec(acting := false));; gap> DotSemilatticeOfIdempotents(S); -"//dot\ngraph graphname {\n node [shape=point]\nranksep=2;\nsubgraph cluster_\ -1{\n1 \n}\nsubgraph cluster_2{\n2 3 5 \n}\nsubgraph cluster_3{\n4 6 7 \n}\nsub\ -graph cluster_4{\n8 \n}\n2 -- 1\n3 -- 1\n4 -- 2\n4 -- 3\n5 -- 1\n6 -- 3\n6 -- \ -5\n7 -- 2\n7 -- 5\n8 -- 4\n8 -- 6\n8 -- 7\n }" +"//dot\ngraph semilattice {\n\tnode[shape=point] ranksep=2 \nsubgraph cluster_\ +1 {\n\t1\n}\nsubgraph cluster_2 {\n\t2\n\t3\n\t5\n}\nsubgraph cluster_3 {\n\t4\ +\n\t6\n\t7\n}\nsubgraph cluster_4 {\n\t8\n}\n\t2 -- 1\n\t3 -- 1\n\t4 -- 2\n\t4\ + -- 3\n\t5 -- 1\n\t6 -- 3\n\t6 -- 5\n\t7 -- 2\n\t7 -- 5\n\t8 -- 4\n\t8 -- 7\n\ +\t8 -- 6\n}\n" # TexString for a transformation gap> TexString(Transformation([1, 1, 1])); @@ -998,27 +638,186 @@ op]\n node {$a$} (c);\n \\path[->] (c) edge [edge] node {$b$} (cb);\ edge [loop]\n node {$a$} (cb);\n \\path[->] (cb) edge [edge] node {\ $b$} (c);\n \\path[->] (cb) edge [edge] node {$c$} (c);\n\\end{tikzpicture}" gap> DotRightCayleyDigraph(FullTransformationMonoid(2)); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1 [label=\"a\"]\n2 [label=\"b\"]\n3\ - [label=\"c\"]\n4 [label=\"cb\"]\n1 -> 1\n1 -> 2\n1 -> 3\n2 -> 2\n2 -> 1\n2 ->\ - 3\n3 -> 3\n3 -> 4\n3 -> 3\n4 -> 4\n4 -> 3\n4 -> 3\n}\n" +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [color\ +=\"#ff00ff\", label=b, style=filled]\n\t2 [label=\"ε\"]\n\t3 [color=\"#00\ +ff00\", label=a, style=filled]\n\t4 [label=ba]\n\t1 -> 2 [color=\"#00ff00\"]\n\ +\t1 -> 3 [color=\"#ff00ff\"]\n\t2 -> 1 [color=\"#00ff00\"]\n\t2 -> 3 [color=\"\ +#ff00ff\"]\n\t3 -> 4 [color=\"#00ff00\"]\n\t3 -> 3 [color=\"#ff00ff\"]\n\t4 ->\ + 3 [color=\"#00ff00\"]\n\t4 -> 3 [color=\"#ff00ff\"]\n// legend context \n\tno\ +de [shape=plaintext] \nsubgraph legend {\n\thead [label=<\n\n\n
b&nbs\ +p;
>\n]\n\ttail [label=<\n\n\n>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:port1:w [co\ +lor=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\thead:por\ +t2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnode [shape=c\ +ircle] node [shape=\"box\"] \n\n}\n" gap> DotLeftCayleyDigraph(FullTransformationMonoid(2)); -"//dot\ndigraph hgn{\nnode [shape=circle]\n1 [label=\"a\"]\n2 [label=\"b\"]\n3\ - [label=\"c\"]\n4 [label=\"cb\"]\n1 -> 1\n1 -> 2\n1 -> 3\n2 -> 2\n2 -> 1\n2 ->\ - 4\n3 -> 3\n3 -> 3\n3 -> 3\n4 -> 4\n4 -> 4\n4 -> 4\n}\n" +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [color\ +=\"#ff00ff\", label=b, style=filled]\n\t2 [label=\"ε\"]\n\t3 [color=\"#00\ +ff00\", label=a, style=filled]\n\t4 [label=ba]\n\t1 -> 2 [color=\"#00ff00\"]\n\ +\t1 -> 3 [color=\"#ff00ff\"]\n\t2 -> 1 [color=\"#00ff00\"]\n\t2 -> 4 [color=\"\ +#ff00ff\"]\n\t3 -> 3 [color=\"#00ff00\"]\n\t3 -> 3 [color=\"#ff00ff\"]\n\t4 ->\ + 4 [color=\"#00ff00\"]\n\t4 -> 4 [color=\"#ff00ff\"]\n// legend context \n\tno\ +de [shape=plaintext] \nsubgraph legend {\n\thead [label=<
 
 
\n\n\n
b&nbs\ +p;
>\n]\n\ttail [label=<\n\n\n>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:port1:w [co\ +lor=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\thead:por\ +t2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnode [shape=c\ +ircle] node [shape=\"box\"] \n\n}\n" gap> S := LeftZeroSemigroup(27);; gap> DotLeftCayleyDigraph(S); -Error, no method found! For debugging hints type ?Recovery from NoMethodFound -Error, no 2nd choice method found for `DotString' on 1 arguments +Error, the 1st argument (an out-regular digraph) must have out-degree at most \ +24, found 27 gap> TikzLeftCayleyDigraph(S); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 2nd choice method found for `TikzString' on 1 arguments gap> DotRightCayleyDigraph(S); -Error, no method found! For debugging hints type ?Recovery from NoMethodFound -Error, no 2nd choice method found for `DotString' on 1 arguments +Error, the 1st argument (an out-regular digraph) must have out-degree at most \ +24, found 27 gap> TikzRightCayleyDigraph(S); Error, no method found! For debugging hints type ?Recovery from NoMethodFound Error, no 2nd choice method found for `TikzString' on 1 arguments +# +gap> S := Semigroup(Transformation([1, 2, 2]), Transformation([2, 2, 2])); + +gap> IsMonoidAsSemigroup(S); +true +gap> Size(S); +2 +gap> DotLeftCayleyDigraph(S); +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [label\ +=\"ε\"]\n\t2 [color=\"#00ff00\", label=b, style=filled]\n\t1 -> 2 [color=\ +\"#00ff00\"]\n\t2 -> 2 [color=\"#00ff00\"]\n// legend context \n\tnode [shape=\ +plaintext] \nsubgraph legend {\n\thead [label=<
 
 
\n\n
>\n]\n\ttail [label=<\n\n
 
>\n]\n\thead:port1:e\n\ttail:port1:w\n\th\ +ead:port1:e -> tail:port1:w [color=\"#00ff00\", constraint=false]\n}\n\tnode [\ +shape=circle] node [shape=\"box\"] \n\n}\n" + +# +gap> F := FreeMonoid("c", "d"); + +gap> AssignGeneratorVariables(F); +gap> R := ParseRelations([c, d], "c^2=c, dc=d, cd^2=d^2, d^5=d^2"); +[ [ c^2, c ], [ d*c, d ], [ c*d^2, d^2 ], [ d^5, d^2 ] ] +gap> S := F / R; + +gap> DotLeftCayleyDigraph(S); +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [label\ +=\"ε\"]\n\t2 [color=\"#00ff00\", label=c, style=filled]\n\t3 [color=\"#ff\ +00ff\", label=d, style=filled]\n\t4 [label=cd]\n\t5 [label=\"d^2\"]\n\t6 [labe\ +l=\"d^3\"]\n\t7 [label=\"d^4\"]\n\t1 -> 2 [color=\"#00ff00\"]\n\t1 -> 3 [color\ +=\"#ff00ff\"]\n\t2 -> 2 [color=\"#00ff00\"]\n\t2 -> 3 [color=\"#ff00ff\"]\n\t3\ + -> 4 [color=\"#00ff00\"]\n\t3 -> 5 [color=\"#ff00ff\"]\n\t4 -> 4 [color=\"#00\ +ff00\"]\n\t4 -> 5 [color=\"#ff00ff\"]\n\t5 -> 5 [color=\"#00ff00\"]\n\t5 -> 6 \ +[color=\"#ff00ff\"]\n\t6 -> 6 [color=\"#00ff00\"]\n\t6 -> 7 [color=\"#ff00ff\"\ +]\n\t7 -> 7 [color=\"#00ff00\"]\n\t7 -> 5 [color=\"#ff00ff\"]\n// legend conte\ +xt \n\tnode [shape=plaintext] \nsubgraph legend {\n\thead [label=<\n\n\n
>\n]\n\ttail [label=<\n\n\n
 
 
>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:p\ +ort1:w [color=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\ +\thead:port2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnod\ +e [shape=circle] node [shape=\"box\"] \n\n}\n" + +# +gap> F := FreeSemigroup("c", "d"); + +gap> AssignGeneratorVariables(F); +gap> R := ParseRelations([c, d], "c^2=c, dc=d, cd^2=d^2, d^5=d^2"); +[ [ c^2, c ], [ d*c, d ], [ c*d^2, d^2 ], [ d^5, d^2 ] ] +gap> S := F / R; + +gap> DotLeftCayleyDigraph(S); +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [color\ +=\"#00ff00\", label=c, style=filled]\n\t2 [color=\"#ff00ff\", label=d, style=f\ +illed]\n\t3 [label=cd]\n\t4 [label=\"d^2\"]\n\t5 [label=\"d^3\"]\n\t6 [label=\ +\"d^4\"]\n\t1 -> 1 [color=\"#00ff00\"]\n\t1 -> 2 [color=\"#ff00ff\"]\n\t2 -> 3\ + [color=\"#00ff00\"]\n\t2 -> 4 [color=\"#ff00ff\"]\n\t3 -> 3 [color=\"#00ff00\ +\"]\n\t3 -> 4 [color=\"#ff00ff\"]\n\t4 -> 4 [color=\"#00ff00\"]\n\t4 -> 5 [col\ +or=\"#ff00ff\"]\n\t5 -> 5 [color=\"#00ff00\"]\n\t5 -> 6 [color=\"#ff00ff\"]\n\ +\t6 -> 6 [color=\"#00ff00\"]\n\t6 -> 4 [color=\"#ff00ff\"]\n// legend context \ +\n\tnode [shape=plaintext] \nsubgraph legend {\n\thead [label=<\n\n\n
>\n]\n\ttail [label=<\n\n\ +\n
 
 
>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:po\ +rt1:w [color=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\ +\thead:port2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnod\ +e [shape=circle] node [shape=\"box\"] \n\n}\n" + +# +gap> F := FreeMonoid("a", "b"); + +gap> AssignGeneratorVariables(F); +gap> R := ParseRelations([a, b], "a^2=a, ba=b, ab^2=b^2, b^5=b^2"); +[ [ a^2, a ], [ b*a, b ], [ a*b^2, b^2 ], [ b^5, b^2 ] ] +gap> S := F / R; + +gap> DotLeftCayleyDigraph(S); +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [label\ +=\"ε\"]\n\t2 [color=\"#00ff00\", label=a, style=filled]\n\t3 [color=\"#ff\ +00ff\", label=b, style=filled]\n\t4 [label=ab]\n\t5 [label=\"b^2\"]\n\t6 [labe\ +l=\"b^3\"]\n\t7 [label=\"b^4\"]\n\t1 -> 2 [color=\"#00ff00\"]\n\t1 -> 3 [color\ +=\"#ff00ff\"]\n\t2 -> 2 [color=\"#00ff00\"]\n\t2 -> 3 [color=\"#ff00ff\"]\n\t3\ + -> 4 [color=\"#00ff00\"]\n\t3 -> 5 [color=\"#ff00ff\"]\n\t4 -> 4 [color=\"#00\ +ff00\"]\n\t4 -> 5 [color=\"#ff00ff\"]\n\t5 -> 5 [color=\"#00ff00\"]\n\t5 -> 6 \ +[color=\"#ff00ff\"]\n\t6 -> 6 [color=\"#00ff00\"]\n\t6 -> 7 [color=\"#ff00ff\"\ +]\n\t7 -> 7 [color=\"#00ff00\"]\n\t7 -> 5 [color=\"#ff00ff\"]\n// legend conte\ +xt \n\tnode [shape=plaintext] \nsubgraph legend {\n\thead [label=<\n\n\n
>\n]\n\ttail [label=<\n\n\n
 
 
>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:p\ +ort1:w [color=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\ +\thead:port2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnod\ +e [shape=circle] node [shape=\"box\"] \n\n}\n" + +# +gap> F := FreeSemigroup("a", "b"); + +gap> AssignGeneratorVariables(F); +gap> R := ParseRelations([a, b], "a^2=a, ba=b, ab^2=b^2, b^5=b^2"); +[ [ a^2, a ], [ b*a, b ], [ a*b^2, b^2 ], [ b^5, b^2 ] ] +gap> S := F / R; + +gap> DotLeftCayleyDigraph(S); +"//dot\ndigraph hgn {\n\tnode [shape=circle] node [shape=\"box\"] \n\t1 [color\ +=\"#00ff00\", label=a, style=filled]\n\t2 [color=\"#ff00ff\", label=b, style=f\ +illed]\n\t3 [label=ab]\n\t4 [label=\"b^2\"]\n\t5 [label=\"b^3\"]\n\t6 [label=\ +\"b^4\"]\n\t1 -> 1 [color=\"#00ff00\"]\n\t1 -> 2 [color=\"#ff00ff\"]\n\t2 -> 3\ + [color=\"#00ff00\"]\n\t2 -> 4 [color=\"#ff00ff\"]\n\t3 -> 3 [color=\"#00ff00\ +\"]\n\t3 -> 4 [color=\"#ff00ff\"]\n\t4 -> 4 [color=\"#00ff00\"]\n\t4 -> 5 [col\ +or=\"#ff00ff\"]\n\t5 -> 5 [color=\"#00ff00\"]\n\t5 -> 6 [color=\"#ff00ff\"]\n\ +\t6 -> 6 [color=\"#00ff00\"]\n\t6 -> 4 [color=\"#ff00ff\"]\n// legend context \ +\n\tnode [shape=plaintext] \nsubgraph legend {\n\thead [label=<\n\n\n
>\n]\n\ttail [label=<\n\n\ +\n
 
 
>\n]\n\thead:port1:e\n\ttail:port1:w\n\thead:port1:e -> tail:po\ +rt1:w [color=\"#00ff00\", constraint=false]\n\thead:port2:e\n\ttail:port2:w\n\ +\thead:port2:e -> tail:port2:w [color=\"#ff00ff\", constraint=false]\n}\n\tnod\ +e [shape=circle] node [shape=\"box\"] \n\n}\n" + # Unbind local variables, auto-generated by etc/tst-unbind-local-vars.py gap> Unbind(S); gap> Unbind(x); From a36f4d9fa0699798307ac58a855a706ab6f8bb67 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Thu, 9 May 2024 17:19:33 +0100 Subject: [PATCH 14/15] ci: clone graphviz --- .github/workflows/ci.yml | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f830c8dd8..8c62865a7 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -50,9 +50,17 @@ jobs: # removed in the fullness of time. LDFLAGS: "-pthread" with: - GAP_PKGS_TO_BUILD: "digraphs io orb datastructures profiling" + GAP_PKGS_TO_BUILD: "Digraphs io orb datastructures profiling" + # TODO remove the following when graphviz is released + GAP_PKGS_TO_CLONE: "james-d-mitchell/Digraphs digraphs/graphviz" GAPBRANCH: ${{ matrix.gap-branch }} ABI: ${{ matrix.ABI }} + - name: "Checkout digraphs graphviz branch (TMP REMOVE)!" + run: | + cd $HOME/gap/pkg/Digraphs + git remote -v + git fetch origin graphviz --depth 1 + git checkout graphviz - name: "Build Semigroups" uses: gap-actions/build-pkg@v1 with: From 795293990ec3f9490a15432102ec561d2d40c9d0 Mon Sep 17 00:00:00 2001 From: "James D. Mitchell" Date: Wed, 15 May 2024 11:30:08 +0100 Subject: [PATCH 15/15] Fixes for upstream changes --- gap/tools/display.gi | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/gap/tools/display.gi b/gap/tools/display.gi index 9a8b31e1a..c4121505b 100644 --- a/gap/tools/display.gi +++ b/gap/tools/display.gi @@ -517,9 +517,11 @@ end); # Dot for semigroups/monoids ############################################################################# +# TODO deprecate InstallMethod(DotString, "for a semigroup", [IsSemigroup], S -> AsString(GraphvizDClasses(S))); +# TODO deprecate InstallMethod(DotString, "for a semigroup", [IsSemigroup, IsRecord], {S, opts} -> AsString(GraphvizDClasses(S, opts))); @@ -665,6 +667,7 @@ function(S) return gv; end); +# TODO deprecate InstallMethod(DotSemilatticeOfIdempotents, "for inverse semigroup with inverse op", [IsInverseSemigroup and IsGeneratorsOfInverseSemigroup], @@ -674,17 +677,21 @@ S -> AsString(GraphvizSemilatticeOfIdempotents(S))); # DotLeft/RightCayleyDigraph ######################################################################## +# TODO deprecate InstallMethod(DotLeftCayleyDigraph, "for a semigroup", [IsSemigroup], S -> AsString(GraphvizLeftCayleyDigraph(S))); +# TODO deprecate InstallMethod(DotRightCayleyDigraph, "for a semigroup", [IsSemigroup], S -> AsString(GraphvizRightCayleyDigraph(S))); +# TODO deprecate InstallMethod(DotLeftCayleyDigraph, "for a semigroup and list of generator names", [IsSemigroup, IsHomogeneousList], {S, names} -> AsString(GraphvizLeftCayleyDigraph(S, names))); +# TODO deprecate InstallMethod(DotRightCayleyDigraph, "for a semigroup and list of generator names", [IsSemigroup, IsHomogeneousList], @@ -1056,8 +1063,8 @@ function(D, node_labels, edge_labels) for m in [1 .. M] do pos := Position(edge_labels, node_labels[m]); if pos <> fail then - GraphvizSetAttr(GraphvizNode(gv, m), "color", edge_colors[pos]); - GraphvizSetAttr(GraphvizNode(gv, m), "style", "filled"); + GraphvizSetAttr(GraphvizNodes(gv)[m], "color", edge_colors[pos]); + GraphvizSetAttr(GraphvizNodes(gv)[m], "style", "filled"); fi; od;