First time here? Check out the FAQ!

Ask Your Question
1

Plot doesn't seem to evaluate my function

asked 13 years ago

Jason gravatar image

I've got a custom function I wrote and I'm trying to plot it. Actually, I'm trying to do an xy density plot but the density plot function was flat (all blue). So I'm trying to plot in a single variable to see what's going on, and the result is all zeroes.

However, when I evaluate my function at several points, none of them are zero. Here's some code showing my function being evaluated at several points vs what plot gives me. Any idea what's going on?

tags = []
for i in range(12):
    for j in range(12):
        tags.append((i*8, j*8, 3))

def getdist((x0,y0,z0),(x1,y1,z1)):
    return sqrt((x1-x0)^2+(y1-y0)^2+(z1-z0)^2.)

def sum_of_distances((x,y,z), tags, maxdist):
    cumdist = 0
    for tag in tags:
        dist = getdist((x,y,z), tag)
        if dist <= maxdist:
            cumdist = cumdist + dist
    return cumdist

#this shows we have real numbers
for i in range(10):
    print sum_of_distances((i,1,1), tags, 30)

#this just shows a y value of 0 (x is 0 to 10)
plot(sum_of_distances((x,1,1), tags, 30),(x,0,10))
Preview: (hide)

2 Answers

Sort by » oldest newest most voted
2

answered 13 years ago

DSM gravatar image

updated 13 years ago

The problem is how binding works in Python. sum_of_distances is a Python function, so it's evaluated immediately. So your plot command is really equivalent to

onepoint = sum_of_distances((x,1,1), tags, 30)
plot(onepoint, (x, 0, 10))

And it so happens that:

sage: sum_of_distances((x,1,1), tags, 30)
0

because this requires testing whether (e.g.) sqrt(x^2+9) < 30, which returns false because Sage doesn't know how to prove it's true (and it's not in general, as x is a symbolic variable which could be anything), so cumdist stays at 0.

One way to get what you want is to use a lambda function to delay evaluation:

plot(lambda x: sum_of_distances((x,1,1), tags, 30),(0,10))

image description

(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)

Preview: (hide)
link

Comments

Great! How do I properly create a 'sage.functions' class instead of a 'function'? Also, perhaps there should be a warning displayed when the plot function is used with a python function as an argument...this is a tricky nuance.

Jason gravatar imageJason ( 13 years ago )

There's no way for us to tell the difference between sum_of_distances((x,1,1), tags, 30) and the return value (at least, without using the preparser), so a warning is probably not possible, or at least, very easy.

Jason Grout gravatar imageJason Grout ( 13 years ago )

Wouldn't it be possible to have an overloaded plot function that behaved differently depending on the input type? When it received a sage class input type it would behave one way, when it received a function input type it would behave another way.

Jason gravatar imageJason ( 13 years ago )

The problem is that the plot function _doesn't_ receive a function input type. It receives the value 0. It's an order-of-evaluation issue.

DSM gravatar imageDSM ( 13 years ago )
0

answered 9 years ago

mariopablo gravatar image

If I say f(x) = sum(k,k,0,x) and then f(2) y get 3, of course, but if I say g(x) = sum(binomial(10,k), k, 0,x) and then g(2), sage doesn't evaluate, just returns the definition with x replaced with 2. Why? Thanks

Preview: (hide)
link

Comments

That's a bug that already has a fix which just needs to be reviewed: http://trac.sagemath.org/ticket/9424

rws gravatar imagerws ( 9 years ago )

Your Answer

Please start posting anonymously - your entry will be published after you log in or create a new account.

Add Answer

Question Tools

Stats

Asked: 13 years ago

Seen: 938 times

Last updated: Oct 14 '15