sympy.solve()没有给LambertW

时间:2018-04-13 13:16:59

标签: python sympy solver inverse

背景
我正在尝试实现一个inverse transform sampling的函数。我使用来计算CDF并获得其反函数。虽然对于一些简单的PDFs我得到了正确的结果,但对于CDF的反函数包含Lambert-W function的PDF,结果是错误的。

示例:
请考虑以下示例CDF:

import sympy as sym

y = sym.Symbol('y')
cdf = (-y - 1) * sym.exp(-y) + 1  # derived from `pdf = x * sym.exp(-x)`
sym.plot(cdf, (y, -1, 5))

enter image description here
现在计算此函数的反函数:

x = sym.Symbol('x')
inverse = sym.solve(sym.Eq(x, cdf), y)
print(inverse)

输出:

[-LambertW((x - 1)*exp(-1)) - 1]

事实上,这只是给定CDF的负面y的左分支:

sym.plot(inverse[0], (x, -0.5, 1))

enter image description here

问题: 如何获得给定CDF的正面分支?

我尝试了什么:

  1. 指定xy仅为正数:

    x = sym.Symbol('x', positive=True)
    y = sym.Symbol('y', positive=True)
    

    即使对于第一张CDF情节,这也没有任何效果。

  2. 使CDF成为Piecewise函数:

    cdf = sym.Piecewise((0, y < 0),
                        ((-y - 1) * sym.exp(-y) + 1, True))
    

    再次没有效果。这里奇怪的是,在另一台计算机上绘制这个函数给出了负y的正确图形为零,但求解正y分支并不能在任何地方工作。 (不同版本?我还必须指定adaptive=Falsesympy.plot以使其在那里工作。)

  3. 使用sympy.solveset代替sympy.solve
    这只会给结果带来无用的ConditionSet(y, Eq(x*exp(y) + y - exp(y) + 1, 0), Complexes(S.Reals x S.Reals, False))。显然,solveset仍然不知道如何处理LambertW函数。来自文档:

      

    当案件未解决或只能解决不完整时,a   使用ConditionSet并充当未评估的solveset对象。 &LT; ...&GT;   还有一些solveset无法做到的事情,旧的solve   可以,如解决非线性多元和&amp; LambertW类型   方程。

  4. 这是一个错误还是我错过了什么?是否有任何解决方法可以获得所需的结果?

1 个答案:

答案 0 :(得分:3)

由sympy产生的逆转几乎是正确的。问题在于LambertW函数在域上有多个分支(-1 / e,0)。默认情况下,它使用上部分支,但是对于您的问题,您需要下部分支。可以通过将第二个参数传递给LambertW并使用值-1来访问下部分支。

inverse = -sym.LambertW((x - 1)*sym.exp(-1), -1) - 1
sym.plot(inverse, (x, 0, 0.999))

给出

enter image description here