(original) (raw)
--- title: "Function `tensorprod()` function in the `stokes` package" author: "Robin K. S. Hankin" output: html_vignette bibliography: stokes.bib link-citations: true vignette: > %\VignetteEngine{knitr::rmarkdown} %\VignetteIndexEntry{tensorprod} %\usepackage[utf8]{inputenc} --- ```{r setup, include=FALSE} set.seed(0) library("spray") 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=""} tensorprod tensorprod2 ``` To cite the `stokes` package in publications, please use @hankin2022_stokes. Function `tensorprod()` returns the tensor cross product of any number of `ktensor` objects; `tensorprod2()` is a lower-level helper function that returns the product of two such objects. These functions use `spraycross()` from the `spray` package [@hankin2022_spray]. ### The tensor cross product In a memorable passage, @spivak1965 states:
Integration on chains
If VVV is a vector space over mathbbR\mathbb{R}mathbbR, we denote the kkk-fold product VtimescdotstimesVV\times\cdots\times VVtimescdotstimesV by VkV^kVk. A function TcolonVklongrightarrowmathbbRT\colon V^k\longrightarrow\mathbb{R}TcolonVklongrightarrowmathbbR is called *multilinear* if for each iii with 1leqslantileqslantk1\leqslant i\leqslant k1leqslantileqslantk we have Tleft(v1,ldots,vi+v′i,ldots,vkright)=Tleft(v1,ldots,vi,ldots,vkright)+Tleft(v1,ldots,v′i,ldots,vkright),Tleft(v1,ldots,avi,ldots,vkright)=aTleft(v1,ldots,vi,ldots,vkright).T\left(v_1,\ldots, v_i + {v'}_i,\ldots, v_k\right)= T\left(v_1,\ldots,v_i,\ldots,v_k\right)+ T\left(v_1,\ldots,{v'}_i,\ldots,v_k\right),\\ T\left(v_1,\ldots,av_i,\ldots,v_k\right)=aT\left(v_1,\ldots,v_i,\ldots,v_k\right).Tleft(v1,ldots,vi+v′i,ldots,vkright)=Tleft(v1,ldots,vi,ldots,vkright)+Tleft(v1,ldots,v′i,ldots,vkright),Tleft(v1,ldots,avi,ldots,vkright)=aTleft(v1,ldots,vi,ldots,vkright). A multilinear function TcolonVklongrightarrowmathbbRT\colon V^k\longrightarrow\mathbb{R}TcolonVklongrightarrowmathbbR is called a *$k$-tensor* on VVV and the set of all kkk-tensors, denoted by mathcalJk(V)\mathcal{J}^k(V)mathcalJk(V), becomes a vector space (over mathbbR\mathbb{R}mathbbR) if for S,TinmathcalJk(V)S,T\in\mathcal{J}^k(V)S,TinmathcalJk(V) and ainmathbbRa\in\mathbb{R}ainmathbbR we define (S+T)(v1,ldots,vk)=S(v1,ldots,vk)+T(v1,ldots,vk)(aS)(v1,ldots,vk)=acdotS(v1,ldots,vk).(S+T)(v_1,\ldots,v_k) = S(v_1,\ldots,v_k) + T(v_1,\ldots,v_k)\\ (aS)(v_1,\ldots,v_k) = a\cdot S(v_1,\ldots,v_k).(S+T)(v1,ldots,vk)=S(v1,ldots,vk)+T(v1,ldots,vk)(aS)(v1,ldots,vk)=acdotS(v1,ldots,vk). There is also an operation connecting the various spaces mathcalJ(V)\mathcal{J}(V)mathcalJ(V). If SinmathcalJk(V)S\in\mathcal{J}^k(V)SinmathcalJk(V) and TinmathcalJl(V)T\in\mathcal{J}^l(V)TinmathcalJl(V), we define the *tensor product* SotimesTinmathcalJk+l(V)S\otimes T\in\mathcal{J}^{k+l}(V)SotimesTinmathcalJk+l(V) by SotimesT(v1,ldots,vk,vk+1,ldots,vk+l)=S(v1,ldots,vk)cdotT(vk+1,ldots,vk+l).S\otimes T(v_1,\ldots,v_k,v_{k+1},\ldots,v_{k+l})= S(v_1,\ldots,v_k)\cdot T(v_{k+1},\ldots,v_{k+l}).SotimesT(v1,ldots,vk,vk+1,ldots,vk+l)=S(v1,ldots,vk)cdotT(vk+1,ldots,vk+l).
- Michael Spivak, 1969 (Calculus on Manifolds, Perseus books). Page 75
Spivak goes on to observe that the tensor product is distributive and associative but not commutative. He then proves that the set of all kkk-fold tensor products phii1otimescdotsotimesphiik,qquad1leqslanti1,ldots,ikleqslantn\phi_{i_1}\otimes\cdots\otimes\phi_{i_k},\qquad 1\leqslant i_1,\ldots,i_k\leqslant nphii1otimescdotsotimesphiik,qquad1leqslanti1,ldots,ikleqslantn [where phii(vj)=deltaij\phi_i(v_j)=\delta_{ij}phii(vj)=deltaij,$v_1,\ldots,v_k$ being a basis for VVV] is a basis for mathcalJk(V)\mathcal{J}^k(V)mathcalJk(V), which therefore has dimension nkn^knk. Function `tensorprod()` evaluates the tensor product and I give examples here. ```{r} (a <- ktensor(spray(matrix(c(1,1,2,1),2,2),3:4))) (b <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),7:9))) ``` Thus a=4phi1otimesphi1+3phi1otimesphi2a=4\phi_1\otimes\phi_1+3\phi_1\otimes\phi_2a=4phi1otimesphi1+3phi1otimesphi2 and b=7phi3otimesphi5+8phi4otimesphi4+9phi7otimesphi3b=7\phi_3\otimes\phi_5+8\phi_4\otimes\phi_4+9\phi_7\otimes\phi_3b=7phi_3otimesphi_5+8phi4otimesphi4+9phi7otimesphi3. Now the cross product aotimesba\otimes baotimesb is given by `tensorprod()`: ```{r} tensorprod(a,b) ``` We can see that the product includes the term 21phi1otimesphi2otimesphi3otimesphi521\phi_1\otimes\phi_2\otimes\phi_3\otimes\phi_521phi_1otimesphi_2otimesphi_3otimesphi_5 and five others. ## Verification Spivak proves that the tensor product is associative and distributive, which are demonstrated here. ```{r} S <- rtensor() T <- rtensor() U <- rtensor() c( left_distributive = S %X% (T+U) == S*T + S*U, right_distributive = (S+T) %X% U == S %X% U + T %X% U, associative = S %X% (T %X% U) == (S %X% T) %X% U ) ``` ### Note on associativity It is interesting to note that, while the tensor product is associative, disord discipline obscures this fact. Consider the following: ```{r} x <- ktensor(spray(matrix(c(1,1,2,1),2,2),1:2)) y <- ktensor(spray(matrix(c(3,4,7,5,4,3),3,2),1:3)) z <- ktensor(spray(matrix(c(1,1,2,1),2,2),1:2)) tensorprod(x, tensorprod(y, z)) tensorprod(tensorprod(x, y), z) ``` The two products are algebraically identical but the terms appear in a different order. ```{r echo=FALSE} rm(T) # tidyup ``` # References