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.

Reply via email to