ASKSAGE: Sage Q&A Forum - Individual question feedhttp://ask.sagemath.org/questions/Q&A Forum for SageenCopyright Sage, 2010. Some rights reserved under creative commons license.Wed, 14 Oct 2015 08:52:53 -0500Plot doesn't seem to evaluate my functionhttp://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/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))Wed, 23 Nov 2011 17:30:38 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/Answer by mariopablo for <p>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.</p>
<p>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?</p>
<pre><code>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))
</code></pre>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?answer=30003#post-id-30003 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? ThanksWed, 14 Oct 2015 08:45:24 -0500http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?answer=30003#post-id-30003Comment by rws for <p>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</p>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=30005#post-id-30005That's a bug that already has a fix which just needs to be reviewed: http://trac.sagemath.org/ticket/9424Wed, 14 Oct 2015 08:52:53 -0500http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=30005#post-id-30005Answer by DSM for <p>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.</p>
<p>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?</p>
<pre><code>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))
</code></pre>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?answer=12934#post-id-12934The 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](/upfiles/13221456968700149.png)
(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)
Thu, 24 Nov 2011 02:46:01 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?answer=12934#post-id-12934Comment by Jason for <p>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 </p>
<pre><code>onepoint = sum_of_distances((x,1,1), tags, 30)
plot(onepoint, (x, 0, 10))
</code></pre>
<p>And it so happens that:</p>
<pre><code>sage: sum_of_distances((x,1,1), tags, 30)
0
</code></pre>
<p>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.</p>
<p>One way to get what you want is to use a lambda function to delay evaluation:</p>
<pre><code>plot(lambda x: sum_of_distances((x,1,1), tags, 30),(0,10))
</code></pre>
<p><img alt="image description" src="/upfiles/13221456968700149.png"/></p>
<p>(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)</p>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20829#post-id-20829Great! 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.Thu, 24 Nov 2011 11:12:21 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20829#post-id-20829Comment by Jason Grout for <p>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 </p>
<pre><code>onepoint = sum_of_distances((x,1,1), tags, 30)
plot(onepoint, (x, 0, 10))
</code></pre>
<p>And it so happens that:</p>
<pre><code>sage: sum_of_distances((x,1,1), tags, 30)
0
</code></pre>
<p>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.</p>
<p>One way to get what you want is to use a lambda function to delay evaluation:</p>
<pre><code>plot(lambda x: sum_of_distances((x,1,1), tags, 30),(0,10))
</code></pre>
<p><img alt="image description" src="/upfiles/13221456968700149.png"/></p>
<p>(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)</p>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20824#post-id-20824There'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.Thu, 24 Nov 2011 18:15:19 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20824#post-id-20824Comment by Jason for <p>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 </p>
<pre><code>onepoint = sum_of_distances((x,1,1), tags, 30)
plot(onepoint, (x, 0, 10))
</code></pre>
<p>And it so happens that:</p>
<pre><code>sage: sum_of_distances((x,1,1), tags, 30)
0
</code></pre>
<p>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.</p>
<p>One way to get what you want is to use a lambda function to delay evaluation:</p>
<pre><code>plot(lambda x: sum_of_distances((x,1,1), tags, 30),(0,10))
</code></pre>
<p><img alt="image description" src="/upfiles/13221456968700149.png"/></p>
<p>(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)</p>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20788#post-id-20788Wouldn'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.Wed, 30 Nov 2011 09:21:24 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20788#post-id-20788Comment by DSM for <p>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 </p>
<pre><code>onepoint = sum_of_distances((x,1,1), tags, 30)
plot(onepoint, (x, 0, 10))
</code></pre>
<p>And it so happens that:</p>
<pre><code>sage: sum_of_distances((x,1,1), tags, 30)
0
</code></pre>
<p>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.</p>
<p>One way to get what you want is to use a lambda function to delay evaluation:</p>
<pre><code>plot(lambda x: sum_of_distances((x,1,1), tags, 30),(0,10))
</code></pre>
<p><img alt="image description" src="/upfiles/13221456968700149.png"/></p>
<p>(BTW, you might be interested in CartesianProduct and in generator expressions-- they can simplify some code like this.)</p>
http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20787#post-id-20787The 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.Wed, 30 Nov 2011 10:11:50 -0600http://ask.sagemath.org/question/8508/plot-doesnt-seem-to-evaluate-my-function/?comment=20787#post-id-20787