--- title: "Function `phi()` function in the `stokes` package" author: "Robin K. S. Hankin" output: html_vignette bibliography: stokes.bib link-citations: true vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{phi} %\usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} set.seed(0) library("stokes") options(rmarkdown.html_vignette.check_title = FALSE) knitr::opts_chunk$set(echo = TRUE) knit_print.function <- function(x, ...){dput(x)} registerS3method( "knit_print", "function", knit_print.function, envir = asNamespace("knitr") ) ``` ```{r out.width='20%', out.extra='style="float:right; padding:10px"',echo=FALSE} knitr::include_graphics(system.file("help/figures/stokes.png", package = "stokes")) ``` ```{r, label=showAlt,comment=""} phi ``` To cite the `stokes` package in publications, please use @hankin2022_stokes. Function `phi()` returns a tensor dual to the standard basis of $V=\mathbb{R}^n$. Here I discuss `phi()` but there is some overlap between this vignette and the `tensorprod` vignette. In a memorable passage, @spivak1965 states (theorem 4.1):

Integration on chains

Let $v_1,\ldots,v_n$ be a basis for $V$, and let $\phi_1,\ldots,\phi_n$ be the dual basis, $\phi_i(v_j)=\delta_{ij}$. Then the set of all $k$-fold tensor products \[ \phi_{i_1}\otimes\cdots\otimes\phi_{i_k}\qquad 1\leqslant i_1,\ldots,i_k\leqslant n \] is a basis for $\mathcal{J}(V)$, which therefore has dimension $n^k$.

- Michael Spivak, 1969 (Calculus on Manifolds, Perseus books). Page 75

Function `phi()` returns a very simple tensor: ```{r} phi(4) ``` First we will verify the properties of `phi()`, using $V=\mathbb{R}^5$, specifically \[ \phi_i(e_j) = \delta_{ij} = \begin{cases} 1, & i=j\\ 0 & i\neq j. \end{cases} \] (package idiom is to use `e()` for basis vectors as opposed to Spivak's $v$). As numerical verification, we will check that $\phi_3(e_2)=0$, $\phi_3(e_3)=1$, $\phi_3(e_4)=0$: ```{r} f <- as.function(phi(3)) c(f(as.matrix(e(2,5))), f(as.matrix(e(3,5))), f(as.matrix(e(4,5)))) ``` A more severe test might be ```{r} aa <- function(n){ outer(seq_len(n), seq_len(n), Vectorize(function(i, j){as.function(phi(i))(as.matrix(e(j, n)))})) } aa(5) ``` Above, we see that the matrix is $I_5$, as expected. Further: ```{r} all(aa(9) == diag(9)) ``` The objects created by `phi()` may be multiplied together using `tensorprod()` or its binary operator `%X%`: ```{r} phi(4) %X% phi(3) %X% phi(5) ``` If we want to create arbitrary tensor products of $\phi$ objects the most natural way would be to use `tensorprod()` repeatedly: ```{r} Reduce(`%X%`,sapply(4:8,phi)) ``` However, function `phi()` simply takes a vector: ```{r} phi(c(2,5,1)) ``` This creates an element of the basis set, in this case $\phi_2\otimes\phi_5\otimes\phi_1$. Verification is straightforward: ```{r} (v <- sample(9)) phi(v) == Reduce(`%X%`,sapply(v,phi)) ``` We will consider an element $X$ of $\mathcal{J}^{2}(V)$ where $V=\mathbb{R}^3$ and construct an explicit basis for it along the lines of Spivak's observation above. ```{r} (X <- ktensor(spray(matrix(c(1,2,3,2,1,1),3,2),1:3))) ``` Thus $X=\phi_1\otimes\phi_2 +2\phi_2\otimes\phi_1 +3\phi_3\otimes\phi_1$. Spivak asserts that $\mathcal{J}^{2}(V)$ has dimension $n^k=3^2=9$. ```{r} 1*phi(c(1,2)) + 2*phi(c(2,1)) + 3*phi(c(3,1)) ``` With a little effort, we can create all $3^2=9$ elements of a basis as follows: ```{r} apply(expand.grid(rep(list(seq_len(3)),2)),1,phi) ``` Or it might be logically better to use ellipsis constructs to pass multiple arguments: ```{r} s <- function(...){phi(unlist(list(...)))} s(3,4,6) ``` Then we could have ```{r} 1*s(1,2) + 2*s(2,1) + 3*s(3,1) 1*s(1,2) + 2*s(2,1) + 3*s(3,1) == X ``` ## Distributivity The tensor product is left- and right distributive. To illustrate this we can use the package to calculate, say, $(2\phi_1+3\phi_2)\otimes(5\phi_3+7\phi_4)$: ```{r} (2*phi(1) + 3*phi(2)) %X% (5*phi(3) + 7*phi(4) ) ``` Above we see package form for the result which is $10\phi_1\phi_3 + 14\phi_1\phi_4 + 15\phi_2\phi_3 + 21\phi_2\phi_4$ in algebraic notation. ## Reconstruction of a given tensor Consider the following tensor ```{r} (b <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),7:9))) ``` We may express $b$ as the sum of its three terms, each with a coefficient: ```{r} 7*phi(c(3,5)) + 8*phi(c(4,4)) + 9*phi(c(7,3)) ``` Above, observe that the order of the terms may differ between the two methods, as per `disordR` discipline [@hankin2022_disordR], but they are algebraically identical: ```{r} b == 7*phi(c(3,5)) + 8*phi(c(4,4)) + 9*phi(c(7,3)) ``` ## Function `Alt()` Function `Alt()` returns an alternating tensor as documented in the `Alt` vignette in the package. It works nicely with `phi()`: ```{r} phi(1:3) Alt(6*phi(1:3)) ``` # References