`wedge()`

and
`wedge2()`

in the `stokes`

package```
function (x, ...)
{
if (nargs() < 3) {
wedge2(x, ...)
}
else {
wedge2(x, Recall(...))
}
}
```

```
function (K1, K2)
{
if (missing(K2)) {
return(K1)
}
if (is.ktensor(K1) | is.ktensor(K2)) {
stop("wedge product only defined for kforms")
}
if (!is.kform(K1) | !is.kform(K2)) {
return(K1 * K2)
}
if (is.empty(K1) | is.empty(K2)) {
return(zeroform(arity(K1) + arity(K2)))
}
kform(spraycross(K1, K2))
}
```

To cite the `stokes`

package in publications, please use
Hankin (2022). In a memorable passage,
Spivak (1965) states:

\(\ldots\) we would like a theorem
analogous to 4.1 [the dimensionality of \(k\)-fold tensor products is \(n^k\)]. Of course, if \(\omega\in\Lambda^k(V)\) and \(\eta\in\Lambda^l(V)\), then \(\omega\otimes\eta\) is usually not in \(\Lambda^{k+l}(V)\). We will therefore
define a new product, the **wedge** product \(\omega\wedge\eta\in\Lambda^{k+l}(V)\)
by

\[ \omega\wedge\eta=\frac{\left(k+l\right)!}{k!l!}\operatorname{Alt}(\omega\otimes\eta),\qquad\omega\in\Lambda^k(V),\eta\in\Lambda^l(V) \]

(The reason for the strange coefficient will appear later).
**- 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:

```
## val
## 2 4 = 5
## 1 3 = 2
```

```
## val
## 11 13 = 11
## 10 12 = 7
```

```
## val
## 1 3 10 12 = 14
## 1 3 11 13 = 22
## 2 4 10 12 = 35
## 2 4 11 13 = 55
```

```
## val
## 10 12 1 3 = 14
## 11 13 1 3 = 22
## 10 12 2 4 = 35
## 11 13 2 4 = 55
```

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:

```
## An alternating linear map from V^2 to R with V=R^2:
## val
## 1 2 = 5
```

```
## An alternating linear map from V^3 to R with V=R^7:
## val
## 3 4 7 = 7
```

```
## An alternating linear map from V^5 to R with V=R^7:
## val
## 1 2 3 4 7 = 35
```

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.

```
## A linear map from V^3 to R with V=R^7:
## val
## 7 4 3 = -7
## 7 3 4 = 7
## 4 7 3 = 7
## 4 3 7 = -7
## 3 7 4 = -7
## 3 4 7 = 7
```

As functions, `y`

and `ty`

are identical:

`## [1] 15.23211 15.23211`

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]
)
```

`## [1] 15.23211`

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()`

:

```
## A linear map from V^5 to R with V=R^7:
## val
## 1 2 3 4 7 = 35
## 2 1 3 7 4 = 35
## 1 2 4 3 7 = -35
## 2 1 3 4 7 = -35
## 1 2 4 7 3 = 35
## 2 1 4 3 7 = 35
## 2 1 4 7 3 = -35
## 1 2 7 3 4 = 35
## 2 1 7 3 4 = -35
## 1 2 3 7 4 = -35
## 1 2 7 4 3 = -35
## 2 1 7 4 3 = 35
```

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:

```
## An alternating linear map from V^5 to R with V=R^7:
## val
## 1 2 3 4 7 = 35
```

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)\). Spivak (1965) 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:

```
## An alternating linear map from V^3 to R with V=R^8:
## val
## 1 3 7 = 6
## 1 2 8 = 5
```

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:

```
## An alternating linear map from V^6 to R with V=R^8:
## val
## 1 2 3 5 6 8 = -15
```

See how function `wedge()`

does the legwork.

Hankin, R. K. S. 2022. “Stokes’s Theorem in
R.” arXiv. https://doi.org/10.48550/ARXIV.2210.17008.

Spivak, M. 1965. *Calculus on Manifolds*. Addison-Wesley.