Sometimes simple notation can make a big difference. One example of this is the **Kronecker delta** function δ_{ij} which is defined to be 1 if *i* = *j* and zero otherwise. Because branching logic is built into the symbol, it can keep branching logic outside of your calculation. That is, you don’t have to write “if … else …” in when doing your calculation. You let the symbol handle it.

The **permutation symbol** ε_{ijk} is similar. It has some branching logic built into its definition, which keeps branching out of your calculation, letting you handle things more uniformly. In other words, the symbol encapsulates some complexity, keeping it out of your calculation. This is analogous to how you might reduce the complexity of a computer program. [1]

## Definition

The permutation symbol, sometimes called the **Levi-Civita symbol**, can have any number of subscripts. If any two of the subscripts are equal, the symbol evaluates to 0. Otherwise, the symbol evaluates to 1 or -1. If you can order the indices with an even number of swaps, the sign of the permutation is 1. If it takes an odd number of swaps, the sign is -1. You could think of putting the indices into a **bubble sort** algorithm and counting whether the algorithm does an even or odd number of swaps.

(There’s an implicit theorem here saying that the definition above makes sense. You could change one order of indices to another by different series of swaps. Two different ways of getting from one arrangement to another may use a different number of swaps, but the number of swaps in both approaches will have the same parity.)

Incidentally, I mentioned even and odd permutations a few days ago in the context of finite simple groups. One of the families of finite simple groups are the alternating groups, the group of even permutations on a set with at least five elements. In other words, permutations whose permutation symbol is 1.

## Examples

For example, ε_{213} = -1 because it takes one adjacent swap, exchanging the 2 and the 1, to put the indices in order. ε_{312} = 1 because you can put the indices in order with two adjacent swaps: 3 <-> 1, then 3 <-> 2. The symbol ε_{122} is 0 because the last two indices are equal.

## Mathematica

You can compute permutation symbols in Mathematica with the function `Signature`

. For example,

Signature[{3, 1, 2}]

returns 1. The function works with more indices as well. For example,

Signature[{3, 1, 2, 5, 4}]

returns -1.

## Python

SymPy has a function `LeviCivita`

for computing the permutation symbol. It also has `Eijk`

as an alias for `LeviCivita`

. Both take a variable number of integers as arguments, not a list of integers as Mathematica does. If you do have a list of integers, you can use the `*`

operator to unpack the list into separate arguments.

from sympy import Eijk, LeviCivita from numpy.random import permutation print( LeviCivita(3, 1, 2) ) print( Eijk(3, 1, 2, 5, 4) ) p = permutation(5) assert(Eijk(*p) == LeviCivita(*p))

## Product formula

When all indices are distinct, the permutation symbol can be computed from a product. For two indices,

For three indices,

and in general

## Cross products

An example use of the permutation symbol is cross products. The *i*th component of the **cross product** of *b* × *c* is

Here we’re using tensor notation where components are indicated by superscripts rather than subscripts, and there’s an implied summation over repeated indices. So here we’re summing over *j* and *k*, each running from 1 to 3.

Similarly, the **triple product** of vectors *a*, *b* and *c* is

This is also the determinant of the matrix whose rows are the vectors *a*, *b*, and *c*. Determinants of larger matrices work the same way.

## Relation to Kronecker delta

This post started out by talking about the more familiar Kronecker delta as an introduction to the permutation symbol. There is a nice relation between the two given below.

If we set *r* = *i* we get the special case

## Related posts

[1] One way of measuring the complexity of a computer program is the maximum number of logic branches in any function. If you have a moderately complex function, and you replace an if-then statement with a call to a small function that has an if-then statement, you’ve reduced the overall complexity. This is sort of what the delta and permutation functions do.

Any particular reason you didn’t mention the sgn function? It looks to me like the product formula could be written as a product of sgn invocations, and then it would always be valid, even when there are duplicated indices. This moves all the conditionals down into the sgn function.

You might find this interesting.

John Ousterhout: “A Philosophy of Software Design” | Talks at Google

https://www.youtube.com/watch?v=bmSAYlu0NcY

You often hear that the cross product is “only for 3D”. But the right hand side of your formula

https://www.johndcook.com/levicivita1.svg

is easy to extend to (n-1) vectors, each with n components.