tensorprod() in the
stokes packagevignettes/tensorprod.Rmd
tensorprod.Rmd
tensorprodfunction (U, ...)
{
if (nargs() < 3) {
tensorprod2(U, ...)
}
else {
tensorprod2(U, Recall(...))
}
}
tensorprod2function (U1, U2)
{
stopifnot(is.ktensor(U1) & is.ktensor(U2))
if (is.empty(U1) | is.empty(U2)) {
return(as.ktensor(cbind(index(U1)[0, ], index(U2)[0,
])))
}
return(ktensor(spraycross(U1, U2)))
}
To cite the stokes package in publications, please use
Hankin (2022b); this function monograph
discusses tensorprod(). 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 (Hankin
2022a).
In a memorable passage, Spivak (1965) states:
Integration on chains
If is a vector space over , we denote the -fold product by . A function is called multilinear if for each with we have
$$ 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). $$
A multilinear function is called a -tensor on and the set of all -tensors, denoted by , becomes a vector space (over ) if for and we define
$$ (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). $$
There is also an operation connecting the various spaces . If and , we define the tensor product by
- 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 -fold tensor products
[where
,
being a basis for
]
is a basis for
,
which therefore has dimension
.
Function tensorprod() evaluates the tensor product and I
give examples here.
## A linear map from V^2 to R with V=R^2:
## val
## 1 1 = 4
## 1 2 = 3
## A linear map from V^2 to R with V=R^7:
## val
## 4 4 = 8
## 7 3 = 9
## 3 5 = 7
Thus
and
.
Now the cross product
is given by tensorprod():
tensorprod(a,b)## A linear map from V^4 to R with V=R^7:
## val
## 1 2 3 5 = 21
## 1 2 7 3 = 27
## 1 1 7 3 = 36
## 1 1 3 5 = 28
## 1 2 4 4 = 24
## 1 1 4 4 = 32
We can see that the product includes the term and five others.
Spivak proves that the tensor product is associative and distributive, which are demonstrated here.
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
)## left_distributive right_distributive associative
## TRUE TRUE TRUE
It is interesting to note that, while the tensor product is associative, disord discipline obscures this fact. Consider the following:
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))## A linear map from V^6 to R with V=R^7:
## val
## 1 1 4 4 1 1 = 8
## 1 2 3 5 1 1 = 2
## 1 1 7 3 1 1 = 12
## 1 1 3 5 1 1 = 4
## 1 2 4 4 1 2 = 2
## 1 1 4 4 1 2 = 4
## 1 2 7 3 1 2 = 3
## 1 2 7 3 1 1 = 6
## 1 1 7 3 1 2 = 6
## 1 2 4 4 1 1 = 4
## 1 2 3 5 1 2 = 1
## 1 1 3 5 1 2 = 2
tensorprod(tensorprod(x, y), z)## A linear map from V^6 to R with V=R^7:
## val
## 1 1 4 4 1 2 = 4
## 1 2 4 4 1 2 = 2
## 1 1 3 5 1 2 = 2
## 1 2 7 3 1 2 = 3
## 1 1 4 4 1 1 = 8
## 1 2 3 5 1 2 = 1
## 1 2 4 4 1 1 = 4
## 1 1 3 5 1 1 = 4
## 1 1 7 3 1 1 = 12
## 1 1 7 3 1 2 = 6
## 1 2 7 3 1 1 = 6
## 1 2 3 5 1 1 = 2
The two products are algebraically identical but the terms appear in a different order.
spray Package.” https://arxiv.org/abs/2210.03856; arXiv. https://doi.org/10.48550/ARXIV.2210.10848.