diff --git a/PackageInfo.g b/PackageInfo.g index 0c19a9f..b73677c 100644 --- a/PackageInfo.g +++ b/PackageInfo.g @@ -2,7 +2,7 @@ SetPackageInfo( rec( PackageName := "RAQ", Subtitle := "Racks And Quandles in GAP", Version := "0.1.0", - Date := "2018-Oct-1", + Date := "2018/10/01", PackageWWWPrefix := Concatenation("http://code.studioinfinity.org/", ~.PackageName), PackageWWWHome := Concatenation(~.PackageWWWPrefix, "/wiki"), @@ -49,7 +49,7 @@ SetPackageInfo( rec( "quasigroups, but more more particularly with racks and quandles. ", "This package builds on fundamentals of non-associative algebra ", "established in the LOOPS package, and ", - "and provides enhanced functionality, libraries, and implementations ", + "provides enhanced functionality, libraries, and implementations ", "as compared to the earlier RIG package ", "on which RAQ is generally modeled." ), diff --git a/README.md b/README.md index caf7d3f..578164f 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,10 @@ #! @Chapter Introduction #! @AutoDocPlainText --> The &RAQ; package provides a variety of facilities for constructing and -computing with one-sided quasigroups, racks, and quandles in ⪆. +computing with one-sided quasigroups, racks, and quandles in ⪆. Highlights +include: +* Constructing quandles from operation tables, groups, or other quandles. +* And more to come.. @@ -53,4 +56,12 @@ Note in particular that &RAQ; generally, unless otherwise specifically requested, produces __left__ quandles and racks. (That is to say, quandles in which for any fixed element $l$, the "left-multiplication by $l$" operation $x\mapsto l*x$ is a permutation of the quandle.) + + +©right; 2018 by Glen Whitney. + +This package may be distributed under the terms and conditions of the GNU +Public License version 3. See the LICENSE file in the package directory +for details. diff --git a/doc/chapters.autodoc b/doc/chapters.autodoc new file mode 100644 index 0000000..6f45f98 --- /dev/null +++ b/doc/chapters.autodoc @@ -0,0 +1,11 @@ +@Chapter construct +@ChapterTitle Constructing One-Sided Quasigroups, Racks, and Quandles. + +@Chapter operate +@ChapterTitle Operations on One-Sided Quasigroups, Racks, and Quandles. + +@Chapter basic +@ChapterTitle Basic Notions + +@Chapter technical +@ChapterTitle Technical Details diff --git a/doc/makedoc.g b/doc/makedoc.g index 706a238..ac66d4d 100644 --- a/doc/makedoc.g +++ b/doc/makedoc.g @@ -3,7 +3,7 @@ LoadPackage("AutoDoc"); AutoDoc(rec( - autodoc := rec(files := ["README.md"]), + autodoc := rec(files := ["README.md", "doc/chapters.autodoc"]), maketest := rec(name := "tst/AutoDoc_tests.g") )); QUIT; diff --git a/lib/structure.gd b/lib/structure.gd index 425ea59..7443bf9 100644 --- a/lib/structure.gd +++ b/lib/structure.gd @@ -2,7 +2,14 @@ ## GAP Categories and representations -## Info class for RAQ +#! @Chapter technical +#! This chapter covers computational/operational aspects of &RAQ; +#! rather than mathematical ones. +#! @Section Messages +#! @Description Controls the level of verbosity of &RAQ;'s informative +#! messages. Use `SetInfoLevel` to set it to 0 to quiet &RAQ; +#! entirely, or to values greater than 1 to yield more details of &RAQ;'s +#! internal algorithms. DeclareInfoClass("InfoRAQ"); ## Self-distributivity @@ -14,63 +21,146 @@ DeclareInfoClass("InfoRAQ"); # (cf. https://arxiv.org/abs/0910.4760). Hence, we implement them in RAQ with # new, non-conflicting terms. -# An element that knows that multiplication in its family is left -# self-distributive: +#! @Chapter basic +#! In order to build up and define one-sided quasigroups, racks, and +#! quandles, &RAQ; must define several lower-level objects and properties, +#! which are documented in this section. Although logically they come before +#! the domain constructors and operations, they are presented afterwards +#! because it's rare that one needs to use them directly when working with +#! &RAQ;. +#! @Section elements +#! @SectionTitle Categories of elements +#! @Description An element x with the property +#! that for all elements y and z in its family, x*(y*z) = +#! (x*y)*(x*z). DeclareCategory("IsLSelfDistElement", IsMultiplicativeElement); +# Have to skip a line because of AutoDoc's convention on documenting +# consecutive declarations. DeclareCategoryCollections("IsLSelfDistElement"); -# An element that knows that multiplication in its family is right -# self-distributive: +#! @Description An element x with the property +#! that for all elements y and z in its family, (y*z)*x = +#! (y*x)*(z*x). DeclareCategory("IsRSelfDistElement", IsMultiplicativeElement); + DeclareCategoryCollections("IsRSelfDistElement"); -# Left self-distributive collections of elements: +#! @Section collections +#! @SectionTitle Categories of collections +#! @Description A collection which satisfies the left self-distributive +#! property (see the description of +#! ) +#! for all triples of elements of the collection. DeclareProperty("IsLSelfDistributive", IsMultiplicativeElementCollection); InstallTrueMethod(IsLSelfDistributive, IsLSelfDistElementCollection); -# Right self-distributive collections of elements: +#! @Description A collection which satisfies the right self-distributive +#! property (see the description of +#! ) +#! for all triples of elements of the collection. DeclareProperty("IsRSelfDistributive", IsMultiplicativeElementCollection); InstallTrueMethod(IsRSelfDistributive, IsRSelfDistElementCollection); ## Idempotence -# There is already a property IsIdempotent on elements, but to definw +# There is already a property IsIdempotent on elements, but to define # structures which will automatically be quandles we need a corresponding # collections category: DeclareCategoryCollections("IsIdempotent"); # Collections in which every element is idempotent +#! @Description A collection in which every element x is +#! **idempotent**, i.e. satisfies x*x=x. DeclareProperty("IsElementwiseIdempotent", IsMultiplicativeElementCollection); InstallTrueMethod(IsElementwiseIdempotent, IsIdempotentCollection); -## Left and right racks and quandles +#! @Description Tests whether obj is a left rack, which by definition +#! is precisely that obj is a left quasigroup (i.e., +#! IsLeftQuasigroup(obj), defined in the &LOOPS; +#! package, is true) and is left self-distributive +#! (i.e., IsLSelfDistributive(obj) is true). +#! @Arguments obj +#! @ItemType Filt DeclareSynonym("IsLeftRack", IsLeftQuasigroup and IsLSelfDistributive); +#! @Description Tests whether obj is a right rack, by definition +#! precisely that it is a right quasigroup and right self-distributive. +#! @Arguments obj +#! @ItemType Filt DeclareSynonym("IsRightRack", IsRightQuasigroup and IsRSelfDistributive); +#! @Description Tests whether obj is a left quandle, which by definition +#! is precisely that obj is a left rack (i.e., +#! IsLeftRack(obj) is true) and every element is idempotent +#! (i.e., IsElementwiseIdempotent(obj) is true). +#! @Arguments obj +#! @ItemType Filt DeclareSynonym("IsLeftQuandle", IsLeftRack and IsElementwiseIdempotent); + +#! @Description Tests whether obj is a right quandle, by definition +#! precisely that it is a right rack and every element is idempotent. +#! @Arguments obj +#! @ItemType Filt DeclareSynonym("IsRightQuandle", IsRightRack and IsElementwiseIdempotent); -## One-sided quasigroups and racks and quandles by generators - -# Returns the closure of under * and LeftQuotient; -# the family of elements of M may be specified, and must be if -# is empty (in which case M will be empty as well). +#! @Chapter construct +#! @Section from_scratch +#! @SectionTitle Direct constructors +#! All of the functions in this section produce magmas (of one of the +#! categories with which &RAQ; is concerned) from data of other (non-domain) +#! types. +#! @BeginAutoDoc +#! @BeginGroup basic_constructors +#! @GroupTitle Basic constructors (from generators) +#! @Description These are the fundamental constructors of these +#! categories. They produce the closure of the specified generators, +#! which are considered to be of the given family, under both the +#! binary operation of the magma, which is always considered to be * in +#! &RAQ;, and the quotient on the specified side. (If +#! family is omitted, these functions attempt to infer it from the +#! generators; if there are no generators then the +#! family must be specified, and note that the resulting magma will +#! be empty.) The resulting magma must satisfy the defining +#! characteristics of the respective category: for the quasigroups, all +#! quotients on the specified side must exist; racks must also satisfy the +#! appropriate self-distributive law; and quandles must also have every +#! element idempotent. +#! @Returns a magma of the named category +#! @GroupInitialArguments [family], [generators] DeclareGlobalFunction("LeftQuasigroup"); -DeclareGlobalFunction("LeftQuasigroupNC"); DeclareGlobalFunction("RightQuasigroup"); -DeclareGlobalFunction("RightQuasigroupNC"); DeclareGlobalFunction("LeftRack"); -DeclareGlobalFunction("LeftRackNC"); DeclareGlobalFunction("RightRack"); -DeclareGlobalFunction("RightRackNC"); DeclareGlobalFunction("LeftQuandle"); -DeclareGlobalFunction("LeftQuandleNC"); DeclareGlobalFunction("RightQuandle"); +#! @EndGroup +#! @BeginGroup unchecked_basic_constructors +#! @GroupTitle Unchecked basic constructors +#! @Description Each function is the same as its checked counterpart, but the +#! family of elements must be specified and no checks that the +#! appropriate axioms are satisfied are performed. They may be used for +#! efficiency when those properties are guaranteed to be satisfied by the +#! generators. NOTE that the behavior of &RAQ; is undefined if the +#! unchecked versions are called on generators that do **not** +#! satisfy the proper axioms. +#! @Returns a magma of the named category +#! @GroupInitialArguments family, generators +DeclareGlobalFunction("LeftQuasigroupNC"); +DeclareGlobalFunction("RightQuasigroupNC"); +DeclareGlobalFunction("LeftRackNC"); +DeclareGlobalFunction("RightRackNC"); +DeclareGlobalFunction("LeftQuandleNC"); DeclareGlobalFunction("RightQuandleNC"); +#! @EndGroup +#! @EndAutoDoc # Underlying operation DeclareGlobalFunction("CloneOfTypeByGenerators"); ## Opposite structures +#! @Section from_quasigroups +#! @SectionTitle Constructors from other one-sided quasigroups +#! All of the functions in this section produce magmas from other objects of +#! similar domain categories. + DeclareCategory("IsOppositeObject", IsMultiplicativeElement); DeclareCategoryCollections("IsOppositeObject"); DeclareAttribute("OppositeFamily", IsFamily); @@ -80,20 +170,44 @@ DeclareSynonym("IsDefaultOppositeObject", DeclareAttribute("OppositeObj", IsMultiplicativeElement); DeclareAttribute("UnderlyingMultiplicativeElement", IsOppositeObject); +#! @Chapter operate +#! @Section basic_info +#! @SectionTitle Basic information + # Attributes for the generators -# Generates the structure by \* and LeftQuotient. Note that for finite -# structures, these are the same as the GeneratorsOfMagma but in general more -# elements might be required to generate the structure just under * +#! @Arguments q +#! @Returns list of elements generating q +#! @Description This produces a list of elements that generate q by +#! `\*` and `LeftQuotient`. There are no guarantees that the list is minimal +#! in any respect. Note that for finite structures, the +#! `GeneratorsOfMagma(q)` will suffice, but in general more +#! elements might be required to generate the structure just under `\*`. DeclareAttribute("GeneratorsOfLeftQuasigroup", IsLeftQuasigroup); -# Generates the structure by \* and \/, same considerations as above +#! @Arguments q +#! @Returns list of elements generating q +#! @Description This produces a list of elements that generate q by +#! `\*` and `\/`, with the same caveats as above. DeclareAttribute("GeneratorsOfRightQuasigroup", IsRightQuasigroup); ## Conversions into quasigroup/rack/quandle +#! @Chapter construct +#! @Section from_scratch +#! @BeginAutoDoc +#! @BeginGroup conversions +#! @GroupTitle Conversions +#! @Description These functions convert a potentially arbitrary +#! collection of elements to one of the categories of objects with +#! which &RAQ; is concerned. The collection must be closed under * +#! and satisfy the appropriate axioms for the conversion to succeed. +#! @Returns a magma of the named category +#! @GroupInitialArguments collection DeclareAttribute("AsLeftQuasigroup", IsCollection); DeclareAttribute("AsLeftRack", IsCollection); DeclareAttribute("AsLeftQuandle", IsCollection); DeclareAttribute("AsRightQuasigroup", IsCollection); DeclareAttribute("AsRightRack", IsCollection); DeclareAttribute("AsRightQuandle", IsCollection); +#! @EndGroup +#! @EndAutoDoc diff --git a/lib/structure.gi b/lib/structure.gi index c6ad2f7..b7e5083 100644 --- a/lib/structure.gi +++ b/lib/structure.gi @@ -489,7 +489,23 @@ OppHelper@ := function(Q, whichgens, cnstr) return opp; end; - +#! @Chapter construct +#! @Section from_quasigroups +#! @Arguments magma +#! @ItemType Attr +#! @Label for various finitely-generated magmas +#! @Description Given `q`, one of the structures covered in &RAQ;, +#! `Opposite(q)` returns a structure which is just the same except the order +#! of the operation is exactly reversed: `a*b` in the new structure means +#! exactly what `b*a` did in the original structure. (This is the same +#! operation as transposing the Cayley table.) Actually, this operation is +#! originally defined in &LOOPS;, and it is extended in &RAQ; to one-sided +#! quasigroups, racks, and quandles. Moreover, since Opposite actually makes +#! sense for an arbitrary magma, &RAQ; makes an effort to extend it to as +#! wide a class of arguments as are easily implemented. Note for example +#! Opposite has no effect on a commutative magma, and &RAQ; +#! recognizes this fact. +#! @Returns a magma of the same category InstallMethod(Opposite, "for a left quasigroup", [IsLeftQuasigroup and HasGeneratorsOfLeftQuasigroup], Q -> OppHelper@(Q, GeneratorsOfLeftQuasigroup, RightQuasigroupNC) @@ -549,6 +565,15 @@ RoughJoinOfFilters@ := function(list, first) return jof; end; +#! @ItemType Meth +#! @Arguments list-of-factors, distinguished-factor +#! @Returns a magma with only the structure common to all factors +#! @Description Extends the `DirectProduct` operation to allow factors that +#! are not even quasigroups, such as the one-sided quasigroups, racks, and +#! quandles with which &RAQ; is concerned. This direct product operation +#! makes its best effort to find the most structured category for the result +#! that it can, given that every factor in the product must lie in that +#! category. InstallOtherMethod(DirectProductOp, "for a list and non-quasigroup magma", [IsList, IsMagma], function (list, first) @@ -669,18 +694,18 @@ end); ## Coversions among the structure types -InstallMethod(AsLeftQuasigroup, "for a left quasigroup", +InstallMethod(AsLeftQuasigroup, "for a left quasigroup", [IsLeftQuasigroup], IdFunc); -InstallMethod(AsLeftRack, "for a left rack", +InstallMethod(AsLeftRack, "for a left rack", [IsLeftRack], IdFunc); -InstallMethod(AsLeftQuandle, "for a left quandle", +InstallMethod(AsLeftQuandle, "for a left quandle", [IsLeftQuandle], IdFunc); -InstallMethod(AsRightQuasigroup, "for a right quasigroup", +InstallMethod(AsRightQuasigroup, "for a right quasigroup", [IsRightQuasigroup], IdFunc); -InstallMethod(AsRightRack, "for a right rack", +InstallMethod(AsRightRack, "for a right rack", [IsRightRack], IdFunc); -InstallMethod(AsRightQuandle, "for a left quandle", - [IsLeftQuandle], IdFunc); +InstallMethod(AsRightQuandle, "for a right quandle", + [IsRightQuandle], IdFunc); AsAStructure@ := function(struc, D) local T,S;