Help understanding lambdify

160 views
Skip to first unread message

Matthew Brett

unread,
Aug 31, 2013, 5:45:49 PM8/31/13
to sympy
Hi,

I was trying to debug a problem I was having with lambdify, and I got
stuck trying to understand the newish 'dummify' changes.

So, it's nice that this works now:

from sympy import symbols, lambdify, sin
from sympy.utilities.lambdify import implemented_function

t = symbols('t')
x = sin
y = x(t)
f = lambdify(y, 2*y, modules=None)
# Evaluates OK
print(f(0))

But I'm not sure why this should not also work:

f = lambdify(y, 2*y, modules='sympy')
# Error evaluating lambda
print(f(0))

In order for this to work, I believe the 'dummify' parameter to
'lambdastr' has to be set to True from the call in 'lambdify', but
this only happens if the strings 'numpy', 'math' or 'mpmath' appear
first in the module list. For example these also fail:

f = lambdify(y, 2*y, modules=numpy)
f = lambdify(y, 2*y, modules=dict(sin=math.sin))
x = implemented_function('x', lambda x : x + 1)
y = x(t)
f = lambdify(y, 2*y, modules='sympy')

Is it easy to explain why these should not work?

Thanks a lot,

Matthew

Jason Moore

unread,
Sep 1, 2013, 12:45:18 PM9/1/13
to sy...@googlegroups.com
Matthew,

This is definitely a bug. We should report in the ticketing system.

The lines here: https://github.com/sympy/sympy/blob/master/sympy/utilities/lambdify.py#L279 don't make a lot of sense to me. I'm not sure why the dummify is set to True only under those specific conditions.

If dummify is overridden to always be true, the function seems to work as expected.

Gilbert Gede made those changes. Maybe he will chime in as to why the code is as it is. I'll look into some fixes and some more tests too.

--
You received this message because you are subscribed to the Google Groups "sympy" group.
To unsubscribe from this group and stop receiving emails from it, send an email to sympy+un...@googlegroups.com.
To post to this group, send email to sy...@googlegroups.com.
Visit this group at http://groups.google.com/group/sympy.
For more options, visit https://groups.google.com/groups/opt_out.

Gilbert Gede

unread,
Sep 1, 2013, 3:02:35 PM9/1/13
to sy...@googlegroups.com
Looks like in lambdify one of the checks for dummification is broken. I'll open a PR in a minute here.

The dummification was only supposed to happen on numerical translation though, so modules='sympy' won't be fixed (or dictionaries). I don't know whether lambdify should always dummify or not though.

-Gilbert

Matthew Brett

unread,
Sep 1, 2013, 3:10:14 PM9/1/13
to sympy
Hi,

On Sun, Sep 1, 2013 at 12:02 PM, Gilbert Gede <gilbe...@gmail.com> wrote:
> Looks like in lambdify one of the checks for dummification is broken. I'll
> open a PR in a minute here.
>
> The dummification was only supposed to happen on numerical translation
> though, so modules='sympy' won't be fixed (or dictionaries). I don't know
> whether lambdify should always dummify or not though.

I understood from the code and the commit messages that dummification
was only meant for numerical translation, but I wasn't sure why. Can
you explain?

Even so, if the user passes a dictionary or their own namespace or
there is an implemented function, it seems to me that they are most
likely doing some numerical translation. Do you agree?

Best,

Matthew

Gilbert Gede

unread,
Sep 1, 2013, 3:38:03 PM9/1/13
to sy...@googlegroups.com
Check out this PR for a discussion of appropriateness of dummification: https://github.com/sympy/sympy/pull/1920

Here's the new PR with the correction: https://github.com/sympy/sympy/pull/2428



Matthew

--
You received this message because you are subscribed to the Google Groups "sympy" group.

Jason Moore

unread,
Sep 1, 2013, 5:15:25 PM9/1/13
to sy...@googlegroups.com
Why not just make dummification an optional argument to lambdify? The user can set it if they desire, otherwise the old behavior happens.

Matthew Brett

unread,
Sep 1, 2013, 7:24:36 PM9/1/13
to sympy
Hi,

On Sun, Sep 1, 2013 at 12:38 PM, Gilbert Gede <gilbe...@gmail.com> wrote:
> Check out this PR for a discussion of appropriateness of dummification:
> https://github.com/sympy/sympy/pull/1920
>
> Here's the new PR with the correction:
> https://github.com/sympy/sympy/pull/2428

If I understand correctly, you are trying to guess whether the person
calling lambdify wants numerical implementations or not.

I agree with your comment on the PR: "But I see your point about
symbols/expressions vs. sub_/big_expressions. But I would think with
lambdify, as it is intended for preparing for numerical evaluation,
that this wouldn't be a concern." :
https://github.com/sympy/sympy/pull/1920

At the moment you try to guess based on whether someone explicitly
passed 'sympy' as the modules argument, or the first argument to
modules (it's not the default).

For example, it might be the case that someone passed 'sympy' as the
first argument, but 'numpy' as the second, and all the functions in
the expression are numpy functions. Or the user might pass 'sympy'
as the modules, and have an implemented function in the expression, so
clearly does want numerical implementation.

So it seems to me the problem here is that you are having to use an
implicit heuristic to determine what the function does, and it would
be hard to guess how to change the behavior of the function without
reading to the code to work out the heuristic.

I think Jason is right - 'dummify' should be an argument to lambdify;
if you really want the heuristic, it should be in the case where
'dummify' is None.

Cheers,

Matthew

Gilbert Gede

unread,
Sep 3, 2013, 11:08:48 PM9/3/13
to sy...@googlegroups.com
I think there were concerns on adding additional arguments to lambdify. That was why I added the dummify flag to the lower-level lambdastr instead, and tried to keep lambdify's interface simple.

I think the logic could be re-written to be a little more robust - maybe not dummifying if a dictionary or 'sympy' is explicitly passed in or implemented functions are provided, and only dummifying if the numeric outputs are going to take precedence over the symbolic outputs?

I guess I'm not completely convinced that there is a benefit for the user in having it as an argument (the 4th optional argument). It's a little simpler to program and read, but it's making the interface more complicated - and if the logic remains in there the code doesn't really end up being "simpler".

I suppose the question is: Are there use cases where dummification is needed, and there are implemented functions or the desired module is 'sympy'? If so, we should add dummification as a flag.

-Gilbert

Matthew Brett

unread,
Sep 4, 2013, 3:16:55 AM9/4/13
to sympy
Hi,

On Tue, Sep 3, 2013 at 8:08 PM, Gilbert Gede <gilbe...@gmail.com> wrote:
> I think there were concerns on adding additional arguments to lambdify. That
> was why I added the dummify flag to the lower-level lambdastr instead, and
> tried to keep lambdify's interface simple.
>
> I think the logic could be re-written to be a little more robust - maybe not
> dummifying if a dictionary or 'sympy' is explicitly passed in or implemented
> functions are provided, and only dummifying if the numeric outputs are going
> to take precedence over the symbolic outputs?

Would you mind giving an example where it would be a very bad idea to
dummify? I read the pull request discussion, but I think the really
nasty examples Stefan gave actually raise errors with dummify. I ask
only because I didn't entirely understand the problem.

For guessing, my guess would be that someone wanted numerical
evaluation if there is:

* a dictionary first argument
* any other namespace than sympy as first argument
* an implemented function anywhere

But I think this is a typical example of zen of Python :

$ python -c 'import this' | grep guess
In the face of ambiguity, refuse the temptation to guess.

> I suppose the question is: Are there use cases where dummification is
> needed, and there are implemented functions or the desired module is
> 'sympy'? If so, we should add dummification as a flag.

Let's say the user does want:

y = x(t)
lambdify(y, 2 * y)

to work. Then, at the moment, they have to guess how we are guessing
that they will tell us that.

Whereas:

lambdify(y, 2 * y, dummify=True)

with a good docstring, seems like it's not much extra work or extra
complexity in the signature, for the reasonably large gain in clarity.

Cheers,

Matthew

Jason Moore

unread,
Sep 4, 2013, 8:16:56 AM9/4/13
to sy...@googlegroups.com
I agree with Matthew here. Adding the argument makes things very unambiguous and it is completely backwards compatible.

Cheers,

Matthew

Gilbert Gede

unread,
Sep 4, 2013, 7:02:25 PM9/4/13
to sy...@googlegroups.com
Fair points. Check out the version of lambdify with dummify as an argument here: https://github.com/sympy/sympy/pull/2428

-Gilbert
Reply all
Reply to author
Forward
0 new messages