Skip to content

Commit

Permalink
Implement dual semigroups
Browse files Browse the repository at this point in the history
  • Loading branch information
MT-resource-bot committed Jun 4, 2018
1 parent cf9ec37 commit 9105017
Show file tree
Hide file tree
Showing 8 changed files with 708 additions and 2 deletions.
135 changes: 135 additions & 0 deletions doc/dual.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,135 @@
#############################################################################
##
#W dual.xml
#Y Copyright (C) 2018 Finn Smith
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##

<#GAPDoc Label="DualSemigroup">
<ManSection>
<Attr Name = "DualSemigroup" Arg = "S"/>
<Returns>The dual semigroup of the given semigroup.</Returns>
<Description>
The dual semigroup of a semigroup <A>S</A> is the
anti-isomorphic semigroup with the same underlying set as <A>S</A>,
where multiplication is reversed. This attribute returns a semigroup
isomorphic to the dual semigroup of <A>S</A>.
<Example>
<![CDATA[
gap> S := Semigroup([Transformation([1, 4, 3, 2, 2]),
> Transformation([5, 4, 4, 1, 2])]);;
gap> D := DualSemigroup(S);
<dual semigroup of <transformation semigroup of degree 5 with 2
generators>>
gap> Size(S) = Size(D);
true
gap> NrDClasses(S) = NrDClasses(D);
true]]></Example> </Description> </ManSection>
<#/GAPDoc>

<#GAPDoc Label="AntiIsomorphismDualSemigroup">
<ManSection>
<Attr Name= "AntiIsomorphismDualSemigroup" Arg = "S"/>
<Returns>
An anti-isomorphism from <A>S</A> to the corresponding dual semigroup.
</Returns>
<Description>
The dual semigroup of <A>S</A> mathematically has the same underlying
set as <A>S</A>, but is represented with a different set of elements in
&Semigroups;. This function returns a mapping which is an anti-isomorphism from
<A>S</A> to its dual.
<Example>
<![CDATA[
gap> S := PartitionMonoid(3);
<regular bipartition *-monoid of size 203, degree 3 with 4 generators>
gap> map := AntiIsomorphismDualSemigroup(S);
MappingByFunction( <regular bipartition *-monoid of size 203,
degree 3 with 4 generators>, <dual semigroup of
<regular bipartition *-monoid of size 203, degree 3 with 4 generators>
>, function( x ) ... end, function( x ) ... end )
gap> inv := InverseGeneralMapping(map);;
gap> x := Bipartition([[1, -2], [2, -3], [3, -1]]);
<block bijection: [ 1, -2 ], [ 2, -3 ], [ 3, -1 ]>
gap> y := Bipartition([[1], [2, -2], [3, -3], [-1]]);
<bipartition: [ 1 ], [ 2, -2 ], [ 3, -3 ], [ -1 ]>
gap> (x ^ map) * (y ^ map) = (y * x) ^ map;
true
gap> x ^ map;
<<block bijection: [ 1, -2 ], [ 2, -3 ], [ 3, -1 ]>
in the dual semigroup>]]></Example> </Description> </ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDualSemigroupElement">
<ManSection>
<Filt Name = "IsDualSemigroupElement" Type = "Category" Arg="elt"/>
<Returns>Returns <K>true</K> if <A>elt</A> has the representation of a dual
semigroup element.</Returns>
<Description>
Elements of a dual semigroup obtained using
<Ref Attr = "AntiIsomorphismDualSemigroup"/> normally lie in this
category. The exception is elements obtained by applying
the map <Ref Attr = "AntiIsomorphismDualSemigroup"/> to elements already
in this category. That is, the elements of a semigroup lie in the
category <Ref Filt="IsDualSemigroupElement"/> if and only if the
elements of the corresponding dual semigroup do not.
<Example>
<![CDATA[
gap> S := SingularPartitionMonoid(4);;
gap> D := DualSemigroup(S);;
gap> s := GeneratorsOfSemigroup(S)[1];;
gap> map := AntiIsomorphismDualSemigroup(S);;
gap> t := s ^ map;
<<block bijection: [ 1, 2, -1, -2 ], [ 3, -3 ], [ 4, -4 ]>
in the dual semigroup>
gap> IsDualSemigroupElement(t);
true
gap> inv := InverseGeneralMapping(map);;
gap> x := t ^ inv;
<block bijection: [ 1, 2, -1, -2 ], [ 3, -3 ], [ 4, -4 ]>
gap> IsDualSemigroupElement(x);
false]]></Example> </Description> </ManSection>
<#/GAPDoc>

<#GAPDoc Label="IsDualSemigroupRep">
<ManSection>
<Filt Name = "IsDualSemigroupRep" Type = "Category" Arg="sgrp"/>
<Returns>Returns <K>true</K> if <A>sgrp</A> is represented as
a dual semigroup.</Returns>
<Description>
Semigroups created using <Ref Func="DualSemigroup"/>
normally have this representation. The exception is semigroups
which are the dual of semigroups already lying in this category.
That is, a semigroup has the representation
<Ref Filt="IsDualSemigroupRep"/> if and only if the corresponding
dual semigroup does not.
<Example>
<![CDATA[
gap> S := Semigroup([Transformation([3, 5, 1, 1, 2]),
> Transformation([1, 2, 4, 4, 3])]);
<transformation semigroup of degree 5 with 2 generators>
gap> D := DualSemigroup(S);
<dual semigroup of <transformation semigroup of degree 5 with 2
generators>>
gap> IsDualSemigroupRep(D);
true
gap> R := DualSemigroup(D);
<transformation semigroup of degree 5 with 2 generators>
gap> IsDualSemigroupRep(R);
false
gap> R = S;
true
gap> T := Range(IsomorphismTransformationSemigroup(D));
<transformation semigroup of size 16, degree 17 with 2 generators>
gap> IsDualSemigroupRep(T);
false
gap> x := Representative(D);
<Transformation( [ 3, 5, 1, 1, 2 ] ) in the dual semigroup>
gap> V := Semigroup(x);
<dual semigroup of <commutative transformation semigroup of degree 5
with 1 generator>>
gap> IsDualSemigroupRep(V);
true]]></Example> </Description> </ManSection>
<#/GAPDoc>
17 changes: 17 additions & 0 deletions doc/z-chap06.xml
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,23 @@ true]]></Log>
<#Include Label = "InverseSubsemigroupByProperty">
<#Include Label = "DirectProduct">
<#Include Label = "WreathProduct">

</Section>

<Section>
<Heading> Dual semigroups </Heading>
Given a semigroup <M>(S, \cdot)</M>, we can consider the anti-isomorphic
semigroup <M>(S, \ast)</M> where we define

<Display> s \ast t = t \cdot s</Display>

for all <M>s,t \in S</M>. This is called the <E>dual semigroup</E> of
<M>(S, \cdot)</M>. While mathematically a semigroup and its dual have
the same underlying set, in &Semigroups; the underlying sets are disjoint.
<#Include Label = "DualSemigroup">
<#Include Label = "IsDualSemigroupRep">
<#Include Label = "IsDualSemigroupElement">
<#Include Label = "AntiIsomorphismDualSemigroup">
</Section>

<Section Label = "Changing the representation of a semigroup">
Expand Down
28 changes: 28 additions & 0 deletions gap/attributes/dual.gd
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
#############################################################################
##
## dual.gd
## Copyright (C) 2018 James D. Mitchell
## Finn Smith
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##

DeclareCategory("IsDualSemigroupElement", IsAssociativeElement);
DeclareCategoryCollections("IsDualSemigroupElement");
DeclareAttribute("DualSemigroup", IsSemigroup);

# Every semigroup is mathematically a dual semigroup
# What we care about is whether it is represented as one
DeclareRepresentation("IsDualSemigroupRep",
IsEnumerableSemigroupRep and
IsDualSemigroupElementCollection,
[]);

DeclareAttribute("DualSemigroupOfFamily", IsFamily);
DeclareAttribute("AntiIsomorphismDualSemigroup", IsSemigroup);
DeclareGlobalFunction("UnderlyingElementOfDualSemigroupElement");

InstallTrueMethod(IsDualSemigroupRep,
IsSemigroup and IsDualSemigroupElementCollection);
210 changes: 210 additions & 0 deletions gap/attributes/dual.gi
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
#############################################################################
##
## dual.gi
## Copyright (C) 2018 James D. Mitchell
## Finn Smith
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
## This file contains an implementation of dual semigroups. We only provide
## enough functionality to allow dual semigroups to work as enumerable
## semigroups. This is to avoid having to install versions of every function
## in Semigroups specially for dual semigroup representations. In some cases
## special functions would be faster.

InstallMethod(DualSemigroup, "for a semigroup",
[IsSemigroup],
function(S)
local dual, fam, filts, map, type;

if IsDualSemigroupRep(S) then
if HasGeneratorsOfSemigroup(S) then
return Semigroup(List(GeneratorsOfSemigroup(S),
x -> UnderlyingElementOfDualSemigroupElement(x)));
fi;
ErrorNoReturn("Semigroups: DualSemigroup: \n",
"this dual semigroup cannot be constructed ",
"without knowing generators,");
fi;

fam := NewFamily("DualSemigroupElementsFamily", IsDualSemigroupElement);
dual := Objectify(NewType(CollectionsFamily(fam),
IsWholeFamily and
IsDualSemigroupRep and
IsAttributeStoringRep),
rec());

filts := IsDualSemigroupElement;
if IsMultiplicativeElementWithOne(Representative(S)) then
filts := filts and IsMultiplicativeElementWithOne;
fi;

type := NewType(fam, filts);
fam!.type := type;

SetDualSemigroupOfFamily(fam, dual);

SetElementsFamily(FamilyObj(dual), fam);
SetDualSemigroup(dual, S);

if HasIsFinite(S) then
SetIsFinite(dual, IsFinite(S));
fi;

if IsTransformationSemigroup(S) then
map := AntiIsomorphismDualSemigroup(dual);
SetAntiIsomorphismTransformationSemigroup(dual, map);
fi;

if HasGeneratorsOfSemigroup(S) then
SetGeneratorsOfSemigroup(dual,
List(GeneratorsOfSemigroup(S),
x -> SEMIGROUPS.DualSemigroupElementNC(dual,
x)));
fi;

if HasGeneratorsOfMonoid(S) then
SetGeneratorsOfMonoid(dual,
List(GeneratorsOfMonoid(S),
x -> SEMIGROUPS.DualSemigroupElementNC(dual,
x)));
fi;
return dual;
end);

SEMIGROUPS.DualSemigroupElementNC := function(S, s)
if not IsDualSemigroupElement(s) then
return Objectify(ElementsFamily(FamilyObj(S))!.type, [s]);
fi;
return s![1];
end;

InstallMethod(AntiIsomorphismDualSemigroup, "for a semigroup",
[IsSemigroup],
function(S)
local dual, inv, iso;

dual := DualSemigroup(S);
iso := function(x)
return SEMIGROUPS.DualSemigroupElementNC(dual, x);
end;

inv := function(x)
return SEMIGROUPS.DualSemigroupElementNC(S, x);
end;
return MappingByFunction(S, dual, iso, inv);
end);

InstallGlobalFunction(UnderlyingElementOfDualSemigroupElement,
"for a dual semigroup element",
function(s)
if not IsDualSemigroupElement(s) then
ErrorNoReturn("Semigroups: UnderlyingElementOfDualSemigroupElement: \n",
"the argument must be an element represented as a dual ",
"semigroup element,");
fi;
return s![1];
end);

################################################################################
## Technical methods
################################################################################

InstallMethod(OneMutable, "for a dual semigroup element",
[IsDualSemigroupElement and IsMultiplicativeElementWithOne],
function(s)
local S, x;
S := DualSemigroupOfFamily(FamilyObj(s));
x := SEMIGROUPS.DualSemigroupElementNC(DualSemigroup(S), s);
return SEMIGROUPS.DualSemigroupElementNC(S, OneMutable(x));
end);

InstallMethod(MultiplicativeNeutralElement, "for a dual semigroup",
[IsDualSemigroupRep],
10, # add rank to beat enumeration methods
function(S)
local m;
m := MultiplicativeNeutralElement(DualSemigroup(S));
if m <> fail then
return SEMIGROUPS.DualSemigroupElementNC(S, m);
fi;
return fail;
end);

InstallMethod(Representative, "for a dual semigroup",
[IsDualSemigroupRep],
function(S)
if HasGeneratorsOfSemigroup(S) then
return GeneratorsOfSemigroup(S)[1];
fi;
return SEMIGROUPS.DualSemigroupElementNC(S, Representative(DualSemigroup(S)));
end);

InstallMethod(Size, "for a dual semigroup",
[IsDualSemigroupRep],
10, # add rank to beat enumeration methods
function(S)
return Size(DualSemigroup(S));
end);

InstallMethod(AsList, "for a dual semigroup",
[IsDualSemigroupRep],
10, # add rank to beat enumeration methods
function(S)
return List(DualSemigroup(S), s -> SEMIGROUPS.DualSemigroupElementNC(S, s));
end);

InstallMethod(\*, "for dual semigroup elements",
IsIdenticalObj,
[IsDualSemigroupElement, IsDualSemigroupElement],
function(x, y)
return Objectify(FamilyObj(x)!.type, [y![1] * x![1]]);
end);

InstallMethod(\=, "for dual semigroup elements",
IsIdenticalObj,
[IsDualSemigroupElement, IsDualSemigroupElement],
function(x, y)
return x![1] = y![1];
end);

InstallMethod(\<, "for dual semigroup elements",
IsIdenticalObj,
[IsDualSemigroupElement, IsDualSemigroupElement],
function(x, y)
return x![1] < y![1];
end);

InstallMethod(ViewObj, "for dual semigroup elements",
[IsDualSemigroupElement], PrintObj);

InstallMethod(PrintObj, "for dual semigroup elements",
[IsDualSemigroupElement],
function(x)
Print("<", ViewString(x![1]), " in the dual semigroup>");
end);

InstallMethod(ViewObj, "for a dual semigroup",
[IsDualSemigroupRep], PrintObj);

InstallMethod(PrintObj, "for a dual semigroup",
[IsDualSemigroupRep],
function(S)
Print("<dual semigroup of ",
ViewString(DualSemigroup(S)),
">");
end);

InstallMethod(ChooseHashFunction, "for a dual semigroup element and int",
[IsDualSemigroupElement, IsInt],
function(x, data)
local H, hashfunc;

H := ChooseHashFunction(x![1], data);
hashfunc := function(a, b)
return H.func(a![1], b);
end;
return rec(func := hashfunc, data := H.data);
end);
Loading

0 comments on commit 9105017

Please sign in to comment.