The previous post used the Lambert *W* function to solve an equation that came up in counting partitions of an integer. The first solution found didn’t make sense in context, but another solution, one on a different branch, did. The default branch *k* = 0 wasn’t what we were after, but the branch *k* = -1 was.

## Branches 0 and -1

The branch corresponding to *k* = 0 is the **principal branch**. In mathematical notation, the *k* is usually a subscript, i.e *W*_{0}(*z*) is the principal branch of the Lambert *W* function. For real *z* ≥ -1/*e* it returns a real value. It’s often what you want, and that’s why it’s the default in software implementations such as SciPy and Mathematica. More on that below.

The only other branch that returns real values for real inputs is *W*_{-1} which returns real values for -1/*e* ≤ *z* < 0.

If you’re working strictly with** real numbers**, you only need to be concerned with branches 0 and -1. If branch 0 doesn’t give you what you expect, try branch -1, if your argument is negative.

## SciPy and Mathematica

SciPy implements *W*_{k} with `lambertw(z)`

. The parameter *k* defaults to 0.

The Mathematica function `ProductLog[`

implements *z*]*W*_{0}(*z*), and `ProductLog[k, z]`

implements *W*_{k}.

Note that Mathematica and Python list their arguments in opposite orders.

## Branch numbering

The branches are numbered in order of their imaginary parts. That is, The imaginary part of *W*_{k} (*z*) is an increasing function of *k*. For example, here is a list of the numerical values of the imaginary parts of *W*_{k} (1) for *k* running from -3 to 3.

Table[N[Im[ProductLog[k, 1]]], {k, -3, 3}] {-17.1135, -10.7763, -4.37519, 0., 4.37519, 10.7763, 17.1135}

Note the zero in the middle because W_{0}(1) is real.

## Recovering *k*

Given *z* and a value *W*_{k} (*z*) with *k* unknown, you can determine *k* with

with the exception that if the expression above is 0 and -1/*e* ≥ *z* < 0 then *k* = -1. See [1].

For example, let *z* = 1 + 2*i* and *w* = *W*_{3} (*z*).

z = 1 + 2 I w = ProductLog[3, z]

Now pretend you don’t know how *w* was computed. When you compute

N[(w + Log[w] - Log[z])/(2 Pi I)]

the result is 3.

## Partition example

The discussion of the *W* function here grew out of a problem with partitions. Specifically, we wanted to solve for *n* such that

is approximately a trillion. We found in the previous post that solutions of the equation

are given by

Our partition problem corresponds to *a* = 1/√48, *b* = -1, *c* = π √(2/3), and *d* = 1/2. We found that the solution we were after came from the *k* = -1 branch.

N[( (b/(c d)) ProductLog[-1, (x/a)^(d/b) c d /b])^(1/d)] 183.852

Even though our final value was real, the intermediate values were not. The invocation of *W*_{-1} in the middle returns a complex value:

N[ProductLog[-1, ((x/a)^(d/b) c d /b)^(1/d)]] -32.5568 - 3.24081 I

We weren’t careful about specifying ranges and branch cuts, but just sorta bulldozed our way to a solution. But it worked: it’s easy to verify that 183.852 is the solution we were after.

***

[1] Unwinding the branches of the Lambert W function by Jeffrey, Hare, and Corless. The Mathematical Scientist 21, 1–7 (1996)