---
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
