【问题标题】:How does sympy simplify ln((exp(x)+1)/exp(x)) to log(1+exp(-x))?sympy 如何将 ln((exp(x)+1)/exp(x)) 简化为 log(1+exp(-x))?
【发布时间】:2016-08-12 18:16:42
【问题描述】:

如果我在 sympy 中使用 simplify() 函数,log((exp(x)+1)/exp(x)) 会简化为 log(1+exp(-x)),但是,当我阅读文档时,简化函数“可能会不必要地慢”,我尝试了其他简化方法,但不是它们中的一个有效,所以我想知道如何在不调用 simple() 的情况下将 ln((exp(x)+1)/exp(x)) 简化为 log(1+exp(-x)) 这样的形式。

【问题讨论】:

  • 您是否体验过该功能“不必要地缓慢”?简化数学函数并不是一件特别容易的事。我会查看 docs.sympy.org/dev/modules/simplify/simplify.html 以帮助了解该函数的作用。
  • 我认为另一个问题是它是不可预测的,因为它会根据它的长度来选择答案。我的工作是比较两个方程,所以我确实需要结果是可预测的,我正在尝试使用简化文档中的函数,但除非我使用 simple(),否则它们中的任何一个都无法工作
  • 我想要的结果立即出现......我使用的是 Sympy 1.0。
  • 我也在使用 1.0,如果我使用 simple() 函数,它只会显示所需的结果,但我真的不想

标签: python sympy


【解决方案1】:

您要使用的确切函数取决于您正在处理的表达式的一般形式。 cancel 显然有效,但也许只是偶然。一般来说,cancel 会取消分子和分母的公因数,例如 cancel((x**2 - 1)/(x - 1)) -> x + 1。我认为它只在这里工作,因为它代表了exp(-x) 的表达式。如果它改为使用exp(x),它不会简化,因为(x + 1)/x 没有任何公因数。这可能就是您在不同版本中看到来自 cancel 的不同结果的原因。请参阅this issue 了解更多信息。

对于这个表达式,我会使用 expand()(或者更有针对性的 expand_mul)。 expand 将分母分配给分子,即(exp(x) + 1)/exp(x) 将变为exp(x)/exp(x) + 1/exp(x)。 SymPy 然后自动将exp(x)/exp(x) 取消为1 并将1/exp(x) 转换为exp(-x)(它们在内部都以相同的方式表示)。

In [1]: log((exp(x)+1)/exp(x)).expand()
Out[1]:
   ⎛     -x⎞
log⎝1 + ℯ  ⎠

tutorial 中有一些简化函数的指南。

【讨论】:

  • 这显然是一个比偶然发现cancel 更好的答案 :)
【解决方案2】:

您可以更直接地使用sympy.polys.polytools.cancel(),它可以作为.cancel() 表达式的方法使用。

>>> from sympy.abc import x
>>> from sympy import *
>>> my_expr = log((exp(x)+1)/exp(x))
>>> my_expr.cancel()
log(1 + exp(-x))

这就是在simplify() 中简化表达式的工作。

一个非常幼稚的基准:

>>> import timeit
>>> %timeit my_expr.simplify()
100 loops, best of 3: 7.78 ms per loop
>>> %timeit my_expr.cancel()
1000 loops, best of 3: 972 µs per loop

编辑:这不是一个稳定的解决方案,我建议您查看asmeurer's answer,他建议使用expand()。

【讨论】:

  • 我注意到它在不同版本中的行为有所不同,我更新到最新版本(1.0.1.dev0)并且它工作得很好但是它不会在版本 1.0 中取消
  • @MichaelYuxiDong cancel 在 SymPy 1.0 中为我工作。
猜你喜欢
  • 2011-10-13
  • 1970-01-01
  • 2018-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多