set.seed(0) library("stokes") library("spray") # needed for spraycross() 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") )
knitr::include_graphics(system.file("help/figures/stokes.png", package = "stokes"))
wedge wedge2
To cite the stokes
package in publications, please use
@hankin2022_stokes. In a memorable passage, @spivak1965 states:
- Michael Spivak, 1969 (Calculus on Manifolds, Perseus books). Page 79
Function wedge()
returns the wedge product of any number of
$k$-forms. Function wedge2()
returns the wedge product of two
$k$-forms, although the idiom is somewhat opaque, especially the
"strange" combinatorial coefficient $(k+l)!/(k!l!)$.
spraycross()
Function wedge()
is essentially a convenience wrapper for
spraycross()
; the meat of wedge2()
is the last line:
kform(spraycross(K1, K2))
. Function spraycross()
is part of the
spray
package and gives a tensor product of sparse arrays,
interpreted as multivariate polynomials:
(a <- spray(matrix(1:4,2,2),c(2,5))) (b <- spray(matrix(c(10,11,12,13),2,2),c(7,11))) spraycross(a,b) spraycross(b,a)
Observe that spraycross()
(and by association wedge()
) is
associative and distributive but not commutative.
wedge2()
Function wedge2()
takes two kforms and we will start with a very
simple example:
(x <- as.kform(cbind(1,2),5)) (y <- as.kform(cbind(3,4,7),7)) wedge2(x,y)
It looks like the combinatorial term has not been included but it has.
We will express x
and y
as tensors (objects of class ktensor
)
and show how the combinatorial term arises.
tx <- as.ktensor(x) # "tx" = tensor 'x' (ty <- as.ktensor(y)) # "ty" = tensor 'y'
As functions, y
and ty
are identical:
M <- matrix(round(rnorm(21),2),7,3) # member of (R^7)^3 c(as.function(y)(M),as.function(ty)(M))
Both are equivalent to
7*( +M[3,1]*M[4,2]*M[7,3] -M[3,1]*M[4,3]*M[7,2] -M[3,2]*M[4,1]*M[7,3] +M[3,2]*M[4,3]*M[7,1] +M[3,3]*M[4,1]*M[7,2] -M[3,3]*M[4,2]*M[7,1] )
We can see that y
is a more compact and efficient representation of
ty
: both are alternating tensors but y
has alternatingness built in
to its evaluation, while ty
is alternating by virtue of including
all permutations of its arguments, with the sign of the permutation.
We can evaluate Spivak's formula (but without the combinatorical term)
for $x\wedge y$ by coercing to ktensors and using tensorprod()
:
(z <- tensorprod(as.ktensor(x),as.ktensor(y)))
Above, each coefficient is equal to $\pm 35$ (the sign coming from the sign of the permutation), and we have $2!3!=12$ rows. We can now calculate $\operatorname{Alt}(z)$, which would have $5!=120$ rows, one per permutation of $[5]$, each with coefficient $\pm\frac{12\times 35}{5!}=\pm 3.5$.
We define $x\wedge y$ to be $\frac{5!}{3!2!}\operatorname{Alt}(z)$, so
each coefficient would be $\pm\frac{5!}{3!2!}\cdot\frac{12\times
35}{5!}=35$. We know that $x\wedge y$ is an alternating form. So to
represent it as an object of class kform
, we need a kform
object
with single index entry 1 2 3 4 7
. This would need coefficient
35, on the grounds that it is linear, alternating, and maps
$\begin{pmatrix}
1&0&0&0&0\
0&1&0&0&0\
0&0&1&0&0\
0&0&0&1&0\
0&0&0&0&0\
0&0&0&0&0\
0&0&0&0&1
\end{pmatrix}$ to $35$; and indeed this is what we see:
wedge(x,y)
So to conclude, the combinatorial term is present in the R idiom, it is just difficult to see at first glance.
First of all we should note that $\Lambda^k(V)$ is a vector space
(this is considered in the kform
vignette). If
$\omega,\omega_i\in\Lambda^k(V)$ and $\eta,\eta_i\in\Lambda^l(V)$ then
\begin{eqnarray} (\omega_1+\omega_2)\wedge\eta &=& \omega_1\wedge\eta+\omega_2\wedge\eta\ \omega\wedge(\eta_1+\eta_2) &=&\omega\wedge\eta_1 + \omega\wedge\eta_2\ \end{eqnarray}
(that is, the wedge product is left- and right- distributive); if $a\in\mathbb{R}$ then
\begin{equation} a\omega\wedge\eta = \omega\wedge a\eta=a(\omega\wedge\eta) \end{equation}
and \begin{equation} \omega\wedge\eta = (-1)^{kl}\eta\wedge\omega. \end{equation}
These rules make expansion of wedge products possible by expressing a general kform in terms of a basis for $\Lambda^k(V)$. @spivak1965 tells us that, if $v_1,\ldots,v_k$ is a basis for $V$, then the set of all
\begin{equation} \phi_{i_1}\wedge\phi_{i_2}\wedge\cdots\wedge\phi_{i_k}\qquad 1\leq i_1 < \cdots < i_k\leq n \end{equation}
is a basis for $\Lambda^k(V)$ where $\phi_i(v_j)=\delta_{ij}$. The package expresses a $k$-form in terms of this basis as in the following example:
(omega <- as.kform(rbind(c(1,2,8),c(1,3,7)),5:6))
In algebraic notation, omega
(or $\omega$) would be
$5\phi_1\wedge\phi_2\wedge\phi_8+6\phi_1\wedge\phi_3\wedge\phi_7$ and
we may write this as $\omega=5\phi_{128}+6\phi_{137}$. To take a
wedge product of this with $\eta=2\phi_{235}+3\phi_{356}$ we would
write
\begin{eqnarray} \omega\wedge\eta &=& (5\phi_{128}+6\phi_{137})\wedge (2\phi_{235}+3\phi_{356})\ &=& 10\phi_{128}\wedge\phi_{235} + 15\phi_{128}\wedge\phi_{356} + 12\phi_{137}\wedge\phi_{235} + 18\phi_{137}\wedge\phi_{356}\ &=& 10\phi_1\wedge\phi_2\wedge\phi_8\wedge\phi_2\wedge\phi_3\wedge\phi_5 + 15\phi_1\wedge\phi_2\wedge\phi_8\wedge\phi_3\wedge\phi_5\wedge\phi_6\&{}&\qquad + 12\phi_1\wedge\phi_3\wedge\phi_7\wedge\phi_2\wedge\phi_3\wedge\phi_5 + 18\phi_1\wedge\phi_3\wedge\phi_7\wedge\phi_3\wedge\phi_5\wedge\phi_6\ &=& 0+ 15\phi_1\wedge\phi_2\wedge\phi_8\wedge\phi_3\wedge\phi_5\wedge\phi_6+0+0\ &=& -15\phi_1\wedge\phi_2\wedge\phi_3\wedge\phi_5\wedge\phi_6\wedge\phi_8 \end{eqnarray}
where we have used the rules repeatedly (especially the fact that $\omega\wedge\omega=0$ for any alternating form). Package idiom would be:
eta <- as.kform(rbind(c(2,3,5),c(3,5,6)),2:3) wedge(omega,eta)
See how function wedge()
does the legwork.
Any scripts or data that you put into this service are public.
Add the following code to your website.
For more information on customizing the embed code, read Embedding Snippets.