Coverage for /usr/lib/python3/dist-packages/scipy/special/_lambertw.py: 67%

3 statements  

« prev     ^ index     » next       coverage.py v7.9.1, created at 2025-06-14 15:55 +0200

1from ._ufuncs import _lambertw 

2 

3 

4def lambertw(z, k=0, tol=1e-8): 

5 r""" 

6 lambertw(z, k=0, tol=1e-8) 

7 

8 Lambert W function. 

9 

10 The Lambert W function `W(z)` is defined as the inverse function 

11 of ``w * exp(w)``. In other words, the value of ``W(z)`` is 

12 such that ``z = W(z) * exp(W(z))`` for any complex number 

13 ``z``. 

14 

15 The Lambert W function is a multivalued function with infinitely 

16 many branches. Each branch gives a separate solution of the 

17 equation ``z = w exp(w)``. Here, the branches are indexed by the 

18 integer `k`. 

19 

20 Parameters 

21 ---------- 

22 z : array_like 

23 Input argument. 

24 k : int, optional 

25 Branch index. 

26 tol : float, optional 

27 Evaluation tolerance. 

28 

29 Returns 

30 ------- 

31 w : array 

32 `w` will have the same shape as `z`. 

33 

34 Notes 

35 ----- 

36 All branches are supported by `lambertw`: 

37 

38 * ``lambertw(z)`` gives the principal solution (branch 0) 

39 * ``lambertw(z, k)`` gives the solution on branch `k` 

40 

41 The Lambert W function has two partially real branches: the 

42 principal branch (`k = 0`) is real for real ``z > -1/e``, and the 

43 ``k = -1`` branch is real for ``-1/e < z < 0``. All branches except 

44 ``k = 0`` have a logarithmic singularity at ``z = 0``. 

45 

46 **Possible issues** 

47 

48 The evaluation can become inaccurate very close to the branch point 

49 at ``-1/e``. In some corner cases, `lambertw` might currently 

50 fail to converge, or can end up on the wrong branch. 

51 

52 **Algorithm** 

53 

54 Halley's iteration is used to invert ``w * exp(w)``, using a first-order 

55 asymptotic approximation (O(log(w)) or `O(w)`) as the initial estimate. 

56 

57 The definition, implementation and choice of branches is based on [2]_. 

58 

59 See Also 

60 -------- 

61 wrightomega : the Wright Omega function 

62 

63 References 

64 ---------- 

65 .. [1] https://en.wikipedia.org/wiki/Lambert_W_function 

66 .. [2] Corless et al, "On the Lambert W function", Adv. Comp. Math. 5 

67 (1996) 329-359. 

68 https://cs.uwaterloo.ca/research/tr/1993/03/W.pdf 

69 

70 Examples 

71 -------- 

72 The Lambert W function is the inverse of ``w exp(w)``: 

73 

74 >>> import numpy as np 

75 >>> from scipy.special import lambertw 

76 >>> w = lambertw(1) 

77 >>> w 

78 (0.56714329040978384+0j) 

79 >>> w * np.exp(w) 

80 (1.0+0j) 

81 

82 Any branch gives a valid inverse: 

83 

84 >>> w = lambertw(1, k=3) 

85 >>> w 

86 (-2.8535817554090377+17.113535539412148j) 

87 >>> w*np.exp(w) 

88 (1.0000000000000002+1.609823385706477e-15j) 

89 

90 **Applications to equation-solving** 

91 

92 The Lambert W function may be used to solve various kinds of 

93 equations. We give two examples here. 

94 

95 First, the function can be used to solve implicit equations of the 

96 form 

97 

98 :math:`x = a + b e^{c x}` 

99 

100 for :math:`x`. We assume :math:`c` is not zero. After a little 

101 algebra, the equation may be written 

102 

103 :math:`z e^z = -b c e^{a c}` 

104 

105 where :math:`z = c (a - x)`. :math:`z` may then be expressed using 

106 the Lambert W function 

107 

108 :math:`z = W(-b c e^{a c})` 

109 

110 giving 

111 

112 :math:`x = a - W(-b c e^{a c})/c` 

113 

114 For example, 

115 

116 >>> a = 3 

117 >>> b = 2 

118 >>> c = -0.5 

119 

120 The solution to :math:`x = a + b e^{c x}` is: 

121 

122 >>> x = a - lambertw(-b*c*np.exp(a*c))/c 

123 >>> x 

124 (3.3707498368978794+0j) 

125 

126 Verify that it solves the equation: 

127 

128 >>> a + b*np.exp(c*x) 

129 (3.37074983689788+0j) 

130 

131 The Lambert W function may also be used find the value of the infinite 

132 power tower :math:`z^{z^{z^{\ldots}}}`: 

133 

134 >>> def tower(z, n): 

135 ... if n == 0: 

136 ... return z 

137 ... return z ** tower(z, n-1) 

138 ... 

139 >>> tower(0.5, 100) 

140 0.641185744504986 

141 >>> -lambertw(-np.log(0.5)) / np.log(0.5) 

142 (0.64118574450498589+0j) 

143 """ 

144 return _lambertw(z, k, tol)