--- title: "The `inner()` function in the `stokes` package" author: "Robin K. S. Hankin" output: html_vignette bibliography: stokes.bib vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{inner} %\usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} set.seed(0) library("stokes") library("quadform") # needed for quad3.form() knitr::opts_chunk$set(echo = TRUE) options(rmarkdown.html_vignette.check_title = FALSE) 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=""} inner ``` To cite the `stokes` package in publications, please use @hankin2022_stokes. @spivak1965, in a memorable passage, states:

The reader is already familiar with certain tensors, aside from members of $V^*$. The first example is the inner product $\left\langle{,}\right\rangle\in{\mathcal J}^2(\mathbb{R}^n)$. On the grounds that any good mathematical commodity is worth generalizing, we define an inner product on $V$ to be a 2-tensor $T$ such that $T$ is symmetric, that is $T(v,w)=T(w,v)$ for $v,w\in V$ and such that $T$ is positive-definite, that is, $T(v,v) > 0$ if $v\neq 0$. We distinguish $\left\langle{,}\right\rangle$ as the usual inner product on $\mathbb{R}^n$.

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

Function `inner()` returns the inner product corresponding to a matrix $M$. Spivak's definition requires $M$ to be positive-definite, but that is not necessary in the package. The inner product of two vectors $\mathbf{x}$ and $\mathbf{y}$ is usually written $\left\langle\mathbf{x},\mathbf{y}\right\rangle$ or $\mathbf{x}\cdot\mathbf{y}$, but the most general form would be $\mathbf{x}^TM\mathbf{y}$. Noting that inner products are multilinear, that is $\left\langle\mathbf{x},a\mathbf{y}+b\mathbf{z}\right\rangle=a\left\langle\mathbf{x},\mathbf{y}\right\rangle + b\left\langle\mathbf{x},\mathbf{z}\right\rangle$ and $\left\langle a\mathbf{x} + b\mathbf{y},\mathbf{z}\right\rangle=a\left\langle\mathbf{x},\mathbf{z}\right\rangle + b\left\langle\mathbf{y},\mathbf{z}\right\rangle$ we see that the inner product is indeed a multilinear map, that is, a tensor. We can start with the simplest inner product, the identity matrix: ```{r} inner(diag(7)) ``` Note how the rows of the tensor appear in arbitrary order, as per `disordR` discipline [@hankin2022_disordR]. Verify: ```{r} x <- rnorm(7) y <- rnorm(7) V <- cbind(x,y) LHS <- sum(x*y) RHS <- as.function(inner(diag(7)))(V) c(LHS=LHS,RHS=RHS,diff=LHS-RHS) ``` Above, we see agreement between $\mathbf{x}\cdot\mathbf{y}$ calculated directly [`LHS`] and using `inner()` [`RHS`]. A more stringent test would be to use a general matrix: ```{r} M <- matrix(rnorm(49),7,7) f <- as.function(inner(M)) LHS <- quad3.form(M,x,y) RHS <- f(V) c(LHS=LHS,RHS=RHS,diff=LHS-RHS) ``` (function `quadform::quad3.form()` evaluates matrix products efficiently; `quad3.form(M,x,y)` returns $x^TMy$). Above we see agreement, to within numerical precision, of the dot product calculated two different ways: `LHS` uses `quad3.form()` and `RHS` uses `inner()`. Of course, we would expect `inner()` to be a homomorphism: ```{r} M1 <- matrix(rnorm(49),7,7) M2 <- matrix(rnorm(49),7,7) g <- as.function(inner(M1+M2)) LHS <- quad3.form(M1+M2,x,y) RHS <- g(V) c(LHS=LHS,RHS=RHS,diff=LHS-RHS) ``` Above we see numerical verification of the fact that $I(M_1+M_2)=I(M_1)+I(M_2)$, by evaluation at $\mathbf{x},\mathbf{y}$, again with `LHS` using direct matrix algebra and `RHS` using `inner()`. Now, if the matrix is symmetric the corresponding inner product should also be symmetric: ```{r} h <- as.function(inner(M1 + t(M1))) # send inner() a symmetric matrix LHS <- h(V) RHS <- h(V[,2:1]) c(LHS=LHS,RHS=RHS,diff=LHS-RHS) ``` Above we see that $\mathbf{x}^TM\mathbf{y} = \mathbf{y}^TM\mathbf{x}$. Further, a positive-definite matrix should return a positive quadratic form: ```{r} M3 <- crossprod(matrix(rnorm(56),8,7)) # 7x7 pos-def matrix as.function(inner(M3))(kronecker(rnorm(7),t(c(1,1))))>0 # should be TRUE ``` Above we see the second line evaluating $\mathbf{x}^TM\mathbf{x}$ with $M$ positive-definite, and correctly returning a non-negative value. ## Alternating forms The inner product on an antisymmetric matrix should be alternating: ```{r} jj <- matrix(rpois(49,lambda=3.2),7,7) M <- jj-t(jj) # M is antisymmetric f <- as.function(inner(M)) LHS <- f(V) RHS <- -f(V[,2:1]) # NB negative as we are checking for an alternating form c(LHS=LHS,RHS=RHS,diff=LHS-RHS) ``` Above we see that $\mathbf{x}^TM\mathbf{y} = -\mathbf{y}^TM\mathbf{x}$ where $M$ is antisymmetric. # References