---
title: "Function `as.function.permutation()` in the permutations package: group actions"
author: "Robin K. S. Hankin"
output: html_vignette
bibliography: permutations.bib
link-citations: true
vignette: >
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteIndexEntry{groupaction}
  %\usepackage[utf8]{inputenc}
---

```{r setup, include=FALSE}
knitr::opts_chunk$set(echo = TRUE)
library("permutations")
set.seed(0)
```

```{r out.width='20%', out.extra='style="float:right; padding:10px"',echo=FALSE}
knitr::include_graphics(system.file("help/figures/permutations.png", package = "permutations"))
```

```{r showfunctionattop}
as.function.permutation
```

To cite the permutations package in publications, please use
@hankin2020.  The `permutations` package was intended to manipulate
and combine permutations, but often one wants to consider the effect
of a permutation on the underlying set, taken to be
$\left[n\right]=\left\lbrace 1,2,\ldots,n\right\rbrace$.  In other
words, we wish to consider a permutation as a function.  In package
idiom, coercing a permutation to a function is straightforward:

```{r label=coercestraight}
g <- as.cycle("(45)(127)")
as.function(g)(4)
```

Above we see that permutation $(45)(127)$ maps 4 to 5.  We can see
from the function body, at the top of the page, that permutations are
coerced to word form.  Function `as.function.permutation()` uses
`as.matrix()` to stop "`x[a,]`" dispatching to `[.word()` and use
matrix extraction instead.  It might be argued that `unclass()` would
be better coding.

Coercion is vectorized:

```{r showvector}
as.function(g)(1:7)
as.function(allperms(4))(3)
as.function(rperm(7,8))(1:7)
```

The second and third forms use the `alist(a = ,
x[cbind(seq_len(nrow(x)),a)])` construction.  We now discuss the
extent to which the underlying permutation group is represented in
package idiom.  Consider the following construction:

```{r showerror, error=TRUE}
(p <- cyc_len(2))
as.function(p)(3)
```

On the one hand, object `p` is a permutation on the set
$[2]=\left\lbrace 1,2\right\rbrace$.  The action of this permutation
on 3 is not defined, and the package returns an error.
Above we effectively see

```{r showmatrixerror, error=TRUE}
t(1:2)[,3]
```

which is the origin of the error.  On the other hand, one might
reasonably hold that the action of $(12)$ on 3 should be 3, on the
grounds that $(12)$ transposes elements 1 and 2 and leaves all other
elements unchanged.  To realise this interpretation we need to ensure
that `p` has underlying set including 3, in this case $\left\lbrace
1,2,3\right\rbrace$.  This is straightforward with `as.word()`:

```{r thisoneworks}
as.function(as.word(p,n=3))(3)
```


### Permutations of sets other than integers

Although the most natural underlying set for a permutation is
the integers, the print method can use different sets.  One
natural set to use is `letters`:

```{r useletters}
set.seed(0)
options(perm_set = letters)
P <- rperm()
P
```

What we _want_ to do is have `as.function(P)("a")` return `"f", "g", "e"` etc.  We may coerce `P` to a function, but this operates [for good reason] on the integers, not letters:

```{r label=doesnotreallywork}
as.function(P)(1)
```

Above we see that `as.function(P)` returns integers, whose print method is not affected by option `perm_set`.  We can get some of the desired functionality by using base R extraction:

```{r label=usebaseextraction}
letters[as.function(P)(1)]
```

but we would like to pass a named letter such as `"b"` (not a number) to the function.  Currently, the only way to do it is somewhat klunky:

```{r label=smewhatklunky}
letters[as.function(P)(which(letters == "b"))]
```

Above we see that `P[1]("b") = "a"`, `P[2]("b") = "c"`, and so on.  Vectorizing this functionality in the argument is even more klunky.  Suppose we wish to determine `P[1]("a"), P[2]("b")`, etc: 

```{r label=evenmoreclunky}
(w <- letters[1:10])
P <- as.word(P, n=10)
letters[as.function(P)(sapply(w, \(x){which(x==letters)}))]
```

Above we see that `P[1]("a") = "f"`, `P[2]("b") = "c"`, etc.


### Note on identity permutation

The ever-problematic identity permutation acts on the empty set so its
functionalization always returns an error:

```{r iderror, error=TRUE}
as.function(id)(4)
```

Again the resolution is to coerce to word form with explicit `n`:

```{r}
as.function(as.word(id,n=4))(4)
```


### References {-}
