python-sympy:当函数定义分段时,lambdify返回错误的答案

时间:2021-10-16 20:20:32

I am baffled at why the answer to the following code is 10 and not 1. Can someone help me understand what is going on with lambdify or what is creating the wrong answer?

我很困惑为什么以下代码的答案是10而不是1.有人可以帮助我理解lambdify正在发生什么或者是什么造成了错误的答案?

import sympy
from sympy.utilities.lambdify import lambdify
from sympy import Function
from sympy.abc import x, y

def kFct(xIndex,loc,k1,k2):
...   if xIndex <= loc:
...     return k1
...   else:
...     return k2
... 
loc = 0.5
k1 = 1
k2 = 10

kfun = lambdify( (x,y), kFct(x,loc,k1,k2) )
print kfun(0,0)
>>> 10

Why isn't the answer k1 or 1, since x = 0, which is less than loc = 0.5?

为什么答案不是k1或1,因为x = 0,小于loc = 0.5?

However, it return the correct answer if I do

但是,如果我这样做,它会返回正确的答案

print kfct(0,loc,k1,k2)
>>> 1

I need to have kfun as a function of x and y, because later on, I use it as part of an argument for an integral. It will also eventually depend on y.

我需要将kfun作为x和y的函数,因为稍后,我将它用作积分参数的一部分。它最终也将取决于y。

I'm using python 2.6.8 on a Mac 10.6.x.

我在Mac 10.6.x上使用python 2.6.8。

2 个解决方案

#1


3  

The arguments to lambdify are evaluated before they're passed, and so you're not actually passing your function to lambdify, you're passing the number 10:

lambdify的参数在传递之前进行评估,因此你实际上并没有将函数传递给lambdify,而是传递数字10:

>>> kFct(x, loc, k1, k2)
10

You get 10 here because

你在这里得到10分,因为

>>> x <= loc
x <= 0.5
>>> bool(x <= loc)
False

and so the second branch is taken. Because of the way Python works, I don't think you'll be able to get this to work -- you can't suppress only one branch being taken. (In principle, a program could do some crazy bytecode introspection, but I'm pretty sure sympy doesn't.)

所以第二个分支被采取。由于Python的工作方式,我认为你不能让它工作 - 你不能只抑制一个分支。 (原则上,一个程序可以做一些疯狂的字节码内省,但我很确定同情不会。)

You could use implemented_function, though:

但您可以使用implemented_function:

>>> f = implemented_function(Function('kFct'), lambda x,y: kFct(x, loc, k1, k2))
>>> kfun = lambdify((x,y), f(x,y))
>>> kfun(0,0)
1
>>> kfun(0.5,0)
1
>>> kfun(0.51,0)
10
>>> kfun(1, 0.0)
10

I'm not sure how much this really benefits you, though, given the extra indirection: I'd probably just work with the function itself (assuming you're ultimately looking for a numerical evaluation of the integral.)

我不确定这对你有多大帮助,但是,考虑到额外的间接性:我可能只是使用函数本身(假设你最终正在寻找积分的数值计算。)

#2


2  

You want to use Piecewise, which represents if branches in a symbolic way that SymPy can work with.

你想使用Piecewise,它代表SymPy可以使用的符号方式的分支。

Here's your example with the values of loc, k1, and k2 put in explicitly. You can of course use them symbolically and replace them later with subs if your code dictates that.

这是你明确放入loc,k1和k2值的例子。你当然可以象征性地使用它们,如果你的代码规定,你可以稍后用subs替换它们。

>>> kFct = Piecewise((1, x < 0.5), (10, True))
>>> kfun = lambdify(x, kFct)
>>> kfun(0)
1
>>> kfun(1)
10

#1


3  

The arguments to lambdify are evaluated before they're passed, and so you're not actually passing your function to lambdify, you're passing the number 10:

lambdify的参数在传递之前进行评估,因此你实际上并没有将函数传递给lambdify,而是传递数字10:

>>> kFct(x, loc, k1, k2)
10

You get 10 here because

你在这里得到10分,因为

>>> x <= loc
x <= 0.5
>>> bool(x <= loc)
False

and so the second branch is taken. Because of the way Python works, I don't think you'll be able to get this to work -- you can't suppress only one branch being taken. (In principle, a program could do some crazy bytecode introspection, but I'm pretty sure sympy doesn't.)

所以第二个分支被采取。由于Python的工作方式,我认为你不能让它工作 - 你不能只抑制一个分支。 (原则上,一个程序可以做一些疯狂的字节码内省,但我很确定同情不会。)

You could use implemented_function, though:

但您可以使用implemented_function:

>>> f = implemented_function(Function('kFct'), lambda x,y: kFct(x, loc, k1, k2))
>>> kfun = lambdify((x,y), f(x,y))
>>> kfun(0,0)
1
>>> kfun(0.5,0)
1
>>> kfun(0.51,0)
10
>>> kfun(1, 0.0)
10

I'm not sure how much this really benefits you, though, given the extra indirection: I'd probably just work with the function itself (assuming you're ultimately looking for a numerical evaluation of the integral.)

我不确定这对你有多大帮助,但是,考虑到额外的间接性:我可能只是使用函数本身(假设你最终正在寻找积分的数值计算。)

#2


2  

You want to use Piecewise, which represents if branches in a symbolic way that SymPy can work with.

你想使用Piecewise,它代表SymPy可以使用的符号方式的分支。

Here's your example with the values of loc, k1, and k2 put in explicitly. You can of course use them symbolically and replace them later with subs if your code dictates that.

这是你明确放入loc,k1和k2值的例子。你当然可以象征性地使用它们,如果你的代码规定,你可以稍后用subs替换它们。

>>> kFct = Piecewise((1, x < 0.5), (10, True))
>>> kfun = lambdify(x, kFct)
>>> kfun(0)
1
>>> kfun(1)
10