--- title: "Antiassociative algebras with R: the `evitaicossa` package" author: "Robin K. S. Hankin" output: html_vignette bibliography: evitaicossa.bib vignette: > %\VignetteIndexEntry{Antiassociative algebra} %\VignetteEngine{knitr::rmarkdown} %\VignetteEncoding{UTF-8} --- ```{r setup, include=FALSE} knitr::opts_chunk$set(echo = TRUE) options(rmarkdown.html_vignette.check_title = FALSE) library("evitaicossa") set.seed(1) ``` ```{r out.width='20%', out.extra='style="float:right; padding:10px"',echo=FALSE} knitr::include_graphics(system.file("help/figures/evitaicossa.png", package = "evitaicossa")) ``` Here I introduce the `evitaicossa` R package for antiassociative algebras. An _algebra_ is a vector space in which the vectors possess a bilinear product. Formally, a vector space is a set $V$ of vectors which form an Abelian group under addition and also satisfy the following axioms: * Compatibility, $a(b\mathbf{v})=(ab)\mathbf{v}$ * Identity, $1\mathbf{v}=\mathbf{v}$ * Distributivity WRT vector addition, $a(\mathbf{u}+\mathbf{v}) = a\mathbf{u}+a\mathbf{v}$ * Distributivity WRT field addition, $(a+b)\mathbf{u} = a\mathbf{u}+b\mathbf{u}$ Above, $\mathbf{u},\mathbf{v}\in V$ are vectors, $a,b$ are scalars [here the real numbers], and $1$ is the multiplicative identity. We also require a bilinear vector product, mapping pairs of vectors to vectors; vector multiplication is denoted using juxtaposition, as in $\mathbf{u}\mathbf{v}$, which satisfies the following axioms: * Right distributivity, $(\mathbf{u}+\mathbf{v})\mathbf{w} = \mathbf{u}\mathbf{w}+ \mathbf{u}\mathbf{w}$ * Left distributivity, $\mathbf{w}(\mathbf{u}+\mathbf{v}) = \mathbf{w}\mathbf{u}+ \mathbf{w}\mathbf{v}$ * Compatibility, $(a\mathbf{u})(b\mathbf{v})=(ab)(\mathbf{u}\mathbf{v})$ Note the absence of commutativity and associativity. Associative algebras seem to be the most common, and examples would include multivariate polynomials [@hankin2022_mvp,@hankin2022_spray], Clifford algebras [@hankin2022_clifford], Weyl algebras [@hankin2022_weyl_arxiv], and free algebras [@hankin2022_freealg]. Non-associative algebras would include the octonions [@hankin2006_onion] and Jordan algebras [@hankin2023_jordan]. Here I consider _antiassociative_ algebras in which the usual associativity relation $\mathbf{u}(\mathbf{v}\mathbf{w})=(\mathbf{u}\mathbf{v})\mathbf{w}$ is replaced by the relation $\mathbf{u}(\mathbf{v}\mathbf{w})=-(\mathbf{u}\mathbf{v})\mathbf{w}$. ## Antiassociative algebras Algebras satisfying $\mathbf{u}(\mathbf{v}\mathbf{w})=-(\mathbf{u}\mathbf{v})\mathbf{w}$ exhibit some startling behaviour. Firstly, in the vector space there are no scalars except for $0\in\mathbb{R}$. Proof: for any $x\in\mathbb{R}$, we have $x^3=x(xx)=-(xx)x=-x^3$; thus $x^3=-x^3$, so $x=0$. Secondly, antiassociative algebras are nilpotent of order 4: $$ (\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d}) = -\mathbf{a}(\mathbf{b}(\mathbf{c}\mathbf{d})) = \mathbf{a}((\mathbf{b}\mathbf{c})\mathbf{d}) = -(\mathbf{a}(\mathbf{b}\mathbf{c}))\mathbf{d} = ((\mathbf{a}\mathbf{b})\mathbf{c})\mathbf{d} = -(\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d}) $$ We see that $(\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d})=-(\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d})$ so $\mathbf{a}\mathbf{b}\mathbf{c}\mathbf{d}$ (however bracketed) must be zero. ## The free antiassociative algebra We consider vector spaces generated by a finite alphabet of symbols $\mathbf{x}_1,\ldots,\mathbf{x}_n$. These will be denoted generally by a single letter, as in $\mathbf{a},\mathbf{b},\ldots,\mathbf{z}$. We now consider the algebra spanned by products of linear combinations of these symbols, subject only to the axioms of an algebra [and the antiassociative relation $\mathbf{u}(\mathbf{v}\mathbf{w})=-(\mathbf{u}\mathbf{v})\mathbf{w}$]. Given an alphabet $\mathbf{x}_1,\ldots,\mathbf{x}_n$, the general form of an element of an antiassociative algebra will be $$ \sum_{i}\alpha_i\mathbf{x}_i + \sum_{i,j}\alpha_{ij}\mathbf{x}_i\mathbf{x}_j+ \sum_{i,j,k}\alpha_{ijk}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k $$ (see @remm2024 for a proof, but note that she uses $\mathbf{x}_i(\mathbf{x}_j\mathbf{x}_k)$ rather than $(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k$ for the triple products; a brief discussion is given in the appendix). In the package, the components of the first term $\sum_{i}\alpha_i\mathbf{x}_i$ are known as "single-symbol" terms [$\mathbf{x}_i$] and coefficients [$\alpha_i$] respectively. Similarly, the components of $\sum_{i,j}\alpha_{ij}\mathbf{x}_i\mathbf{x}_j$ are known as the "double-symbol" terms and coefficients; and the components of $\sum_{i,j,k}\alpha_{ijk}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k$ are the "triple-symbol" terms and coefficients. Addition is performed elementwise among the single-, double-, and triple- components; the result is the (formal) composition of the three results. Given $$A= \sum_{i}\alpha_i\mathbf{x}_i + \sum_{i,j}\alpha_{ij}\mathbf{x}_i\mathbf{x}_j+ \sum_{i,j,k}\alpha_{ijk}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k $$ $$B= \sum_{i}\beta_i\mathbf{x}_i + \sum_{i,j}\beta_{ij}\mathbf{x}_i\mathbf{x}_j+ \sum_{i,j,k}\beta_{ijk}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k $$ (where the sums run from $1$ to $n$), we define the sum $A+B$ to be $$ \sum_{i}(\alpha_i+\beta_i)\mathbf{x}_i + \sum_{i,j}(\alpha_{ij}+\beta_{ij})\mathbf{x}_i\mathbf{x}_j+ \sum_{i,j,k}(\alpha_{ijk}+\beta_{ijk})(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k $$ Multiplication is slightly more involved. We define the product $AB$ to be $$ \sum_{i,j}\alpha_i\beta_{ij}\mathbf{x}_i\mathbf{x}_j +\sum_{i,j,k}\alpha_{ij}\beta_{k}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k -\sum_{i,j,k}\alpha_i\beta_{jk}(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k. $$ The minus sign in front of the third term embodies antiassociativity. ## The `evitaicossa` package The `evitaicossa` package implements these relations in the context of an R-centric suite of software. I give some examples of the package in use. A good place to start is function `raaa()`, which returns a simple random element of the free antiassociative algebra: ```{r label=showraaa} raaa() ``` (the default alphabet for this command is $\left\lbrace\mathbf{a},\mathbf{b},\mathbf{c},\mathbf{d}\right\rbrace$). We see the print method for the package which shows some of the structure of the object. This one has some single-symbol elements, some double-symbol and some triple-symbol elements. It is possible to create elements using the `aaa()` or `as.aaa()` functions: ```{r label=makexx1yz} x <- as.aaa(c("p","q","r")) x1 <- aaa(s1 = c("p","r","x"),c(-1,5,6)) y <- aaa(d1 = letters[1:3],d2 = c("foo","bar","baz"),dc=1:3) z <- aaa( t1 = c("bar","bar","bar"), t2 = c("q","r","s"), t3 = c("foo","foo","bar"), tc = 5:7) ``` And then apply arithmetic operations to these objects: ```{r label=applyarith} x x1 x+x1 ``` (above, note the cancellation in `x+x1`). Multiplication is also implemented (package idiom is to use an asterisk `*`): ```{r label=usemult} x*(x1+y) ``` Check: ```{r label=checkdistributivity} x*(x1+y) == x*x1 + x*y ``` We end with a remarkable identity: $$ (\mathbf{a}+\mathbf{a}\mathbf{x})(\mathbf{b} + \mathbf{x}\mathbf{b})=\mathbf{a}\mathbf{b} $$ Numerically: ```{r label=checkremarkable} a <- raaa() b <- raaa() x <- raaa() (a+a*x)*(b+x*b) == a*b ``` ## Extract and replace methods Because of the tripartite nature of antiassociative algebra, the package provides three families of extraction methods: `single()`, `double()` and `triple()`, which return the different components of an object: ```{r label=showsingledoubletriple} a single(a) double(a) triple(a) ``` The corresponding replacement methods are also implemented: ```{r label=extract123} single(a) <- 0 a double(a) <- double(b) * 1000 a ``` Square bracket extraction and replacement is also implemented: ```{r label=showsquarebracketextract} (a <- raaa(s=5)) a[s1=c("c","e"),t1="c",t2="d",t3="d"] ``` Above we pass named arguments (\code{s1} _et seq._) and the appropriate `aaa` object is returned. Zero coefficients are discarded. This mode also implements replacement methods: ```{r label=showsquarebracketreplace} (a <- raaa(s=5)) a[s1="a",d1=c("c","w"),d2=c("d","w")] <- 888 a ``` The other square bracket method is to pass an (unnamed) character vector: ```{r unnamedcharacter} (a <- raaa()) ``` ### Note on `disordR` discipline If we try to access the symbols or coefficients of an `aaa` object [functions `s1()` and `sc()` respectively], we get a `disord` object [@hankin2022_disordR]. Suppose we wish to extract the single-symbol terms and the single-symbol coefficients: ```{r showdissingle} x s1(x) sc(x) ``` See how the hash codes of the symbols and coeffients match. However, the double-symbol terms and coefficients, while internally matching, differ from the single-symbol stuff: ```{r showdisdouble} list(d1(x),d2(x),dc(x)) ``` Above, see how the double-symbol terms and double-symbol coefficients have consistent hashes, but do not match the single-symbol objects (or indeed the triple-symbol objects). ## Matrix index extraction If square bracket extraction is given an index that is a matrix, it is interpreted rowwise: ```{r label=matrixindex} l <- letters[1:3] (a <- aaa(s1=l,sc=1:3, d1=l,d2=rev(l),dc=3:1,t1=l,t2=l,t3=rev(l),tc=1:3)) a[cbind(l,l)] a[cbind(rev(l),l,l)] <- 88 a ``` ## Note on generalized antiassociativity We may generalize antiassociativity to $\mathbf{a}(\mathbf{b}\mathbf{c})=k(\mathbf{a}\mathbf{b})\mathbf{c}$. Thus associativity is recovered if $k=1$ and antiassociativity if $k=-1$. Then the nilpotence argument becomes: $$ (\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d}) = k^{-1}\mathbf{a}(\mathbf{b}(\mathbf{c}\mathbf{d})) = \mathbf{a}((\mathbf{b}\mathbf{c})\mathbf{d}) = k(\mathbf{a}(\mathbf{b}\mathbf{c}))\mathbf{d} = k^2((\mathbf{a}\mathbf{b})\mathbf{c})\mathbf{d} = k(\mathbf{a}\mathbf{b})(\mathbf{c}\mathbf{d}) $$ The value of $k$ may be set at compile-time by editing file `src/anti.h`. The line in question reads: ``` #define K -1 // a(bc) == K(ab)c ``` but it is possible to change the value of `K`. Note that this will cause `test_aac.R`, one of the `testthat` suite, to fail `R CMD check`. ### Appendix As noted above, @remm2024 uses $\mathbf{x}_i(\mathbf{x}_j\mathbf{x}_k)$ rather than $(\mathbf{x}_i\mathbf{x}_j)\mathbf{x}_k$ for the triple products. I chose the latter because R idiom for multiplication is left associative: ```{r makefoo} x <- 3 class(x) <- "foo" `*.foo` <- function(x,y){x + y + x} print.foo <- function(x){print(unclass(x))} c(`(x*x)*x` = (x*x)*x, `x*(x*x)` = x*(x*x), `x*x*x` = x*x*x) ``` Above we see that `x*x*x` is interpreted as `(x*x)*x`, which is why the sign convention in the package was adopted. ## References