On Apr 2, 2010, at 9:41 PM, G B wrote:
Thanks for the detailed response, Simon. Please understand that I'm
not being critical of Sage-- quite the contrary, I'm excited about
what it might offer me once I master it.
I think you touch on one key to the problem-- I'm not a
mathematician, I'm an engineer. While most of the world would
certainly accuse us of being sloppy dressers, mathematicians are one
of the few groups that can legitimately accuse us of being sloppy
thinkers. I think that brand of sloppy thinking is what is at issue
here, and when I say "work around" I mean "become tolerant of".
Sage has already encouraged me to learn more about ring theory than
I ever would have needed otherwise, but getting completely different
results when executing plot(f(x),(x,0,2*pi)) vs. executing plot(f,
(0,2*pi)) started playing on my patience a bit and has me wondering
if I'm simply using an irreconcilably wrong tool for the job. I
think the intention of both of those statements is the same, and
thus should yield the same result, and my suspicion is that the
reason they don't is an artifact of the plumbing, but I may be
missing something.
A good way to think about it is this: Python expressions are evaluated
greedily, from the inside out. Thus
sage: plot(f(x),(x,0,2*pi))
is the same as
sage: A = f(x) # A is now sin(x) + 0.619...
sage: B = (x,0,2*pi)
sage: plot(A, B)
When you write something like sin(x), sin is actually getting called
with the argument x, and the result is sin evaluated at the
indeterminate x (in other words, it's not just returning the old thing
back again). As a more concrete example.
sage: g(x) = sin(x) + sqrt(x)
sage: g(x)
sqrt(x) + sin(x) # g was called with x and plugged in x for x
sage: g(5)
sqrt(5) + sin(5)
sage: var('y')
y
sage: g(y)
sqrt(y) + sin(y)
sage: g(x+y)
sqrt(x + y) + sin(x + y)
It's not the f(x)=sin(x)+T.get_random_element() form that troubles
me though, for the record, I did try 'f(x)=sin(x)
+T.get_random_element(x)'. Expectedly, it doesn't like having an
unwanted argument shoved down its throat.
What still feels awkward to me is how constructs like this behave:
var('x')
T=RealDistribution('gaussian',1)
f=lambda x: T.get_random_element()
g(x)=sin(x)+f(x)
To my mind, the way that is handled is particularly confusing.
[f(1),f(2),f(3)] --> [-0.568652852118, 0.912307924442, 1.35997405644]
but,
[g(1),g(2),g(3)] --> [sin(1) - 0.176035204293, sin(2) -
0.176035204293, sin(3) - 0.176035204293]
In other words, calling f repeatedly gives different results each
time, but calling g repeatedly does not.
That may be a case where the parenthetical syntax conspires with the
overloaded meanings of "function" to expose my sloppy thinking, but
it also kind of looks like a trap waiting to be triggered.
If sin(x) and f(x) are fundamentally different entities, and my
engineering mind isn't completely convinced that they should be,
Yes, they are very different. The first are "expression-like"
functions, where it makes sense to differentiate, integrate, typeset,
and otherwise manipulate them as mathematical objects. "Sin" falls
into this category. The other type are "procedures" which are are
really arbitrary chunks of code which are the ones native to Python
(and essentially every other procedural programming language). These
are the ones that generate random numbers, test for primality, fetch
webpages, save files, etc. Plot itself is such a "function." It
doesn't makes much sense to differentiate or typeset such functions,
but they can be called.
Both types of functions are clearly essential, the confusion arises in
the fact that it's possible to evaluate (and, sometimes, plot) both
kinds. That being said, I think it should easier (and more natural) to
try to do what you're trying to do here.
then the syntax should prevent the construction of g in such a
manner. Either execution of f should be deferred until g is called
with a parameter, as I would expect, or an error should be thrown
for providing illegal arguments to operator '+'.
The problem is that the two terms are evaluated before the + operator
is hit, i.e.
sage: g(x) = sin(x) + f(x)
is the same as
sage: A = sin(x) # actually calls sin (resulting in sin(x))
sage: B = f(x) # actually calls f (resulting in 0.619....)
sage: g(x) = A + B # tries to add (which is just fine)
If I want g(x) defined as sin(x) plus the result of f(x) as x is
defined at the definition of g, then the syntax should highlight
that by forcing something like g(x)=sin(x) + `f(x)`
To get something deferred, which sounds like what you want, you could
abandon the g(x) = ... syntax completely and always use lambda (or def)
sage: g = lambda x: sin(x) + f(x)
or
sage: def g(x):
... return sin(x) + f(x)
It may take some getting used to, but functions can even return other
functions. For example, you could write:
def add_noise(f, T):
return lambda x: f(x) + T.get_random_element()
sage: g(x) = 10*sin(x)
sage: noisy_g = add_noise(g, RealDistribution('gaussian',1))
sage: noisy_g(4)
10*sin(4) - 0.885770378312
sage: noisy_g(4)
10*sin(4) + 0.133895528457
sage: plot(noisy_g, (-1, 1))
- Robert
--
To post to this group, send email to [email protected]
To unsubscribe from this group, send email to
[email protected]
For more options, visit this group at
http://groups.google.com/group/sage-support
URL: http://www.sagemath.org
To unsubscribe, reply using "remove me" as the subject.