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;