Stan Schymanski wrote:
> Dear all,
> 
> Could anyone tell me how to controll the order in which arguments are
> evaluated when they are passed to python functions? It seems that the
> functions are evaluated first and then the variables are substituted,
> which leads to failures in the following example:
> 
> var('c')
> 
> def piece(c,x):
>     if x < 1.:
>         return c*x^2
>     if x >= 1.:
>         return 1/x-c
> 
> plot(piece(0.2,x),0,2)
>     Traceback (click to the left for traceback)
>     ...
>     TypeError: no way to make fast_float from None
> 
> numerical_integral(piece(0.2,x),0,2)
>     Traceback (click to the left for traceback)
>     ...
>     TypeError: a float is required
> 
> How can I get sage to substitute the values for x before calling piece
> (0.2,x)?

You are correct.  In both of these cases, you are calling piece(0.2,x) 
and putting that result in for the first argument of plot and 
numerical_integral.  Instead, you want the first argument to be a call 
to piece(0.2,x), so put a function in that returns piece, rather than 
putting piece in there that returns an expression.

There are several ways to do this (these below are not comprehensive):

Note that I define your function slightly more efficiently (I only 
compare x once)

sage: def piece(c,x):
....:     if x<1.:
....:         return c*x^2
....:     else:
....:         return 1/x-c
....:

Now I put in the first argument a function which calls piece for every 
input value.

sage: plot(lambda x: piece(0.2,x), 0, 2)

Another way to do it is to use the partial function in the functools 
module.  This basically does the same thing as above, but seems more 
efficient.

sage: from functools import partial
sage: piece02 = partial(piece, 0.2)
sage: piece02(2)
0.300000000000000
sage: plot(piece02, 0, 2)


Unfortunately, we haven't extended fast_float to handle an if statement, 
so fast_float won't work on the above example.  Well, except that we 
could use fast_float inside of our piecewise function.

sage: f1 = lambda x: piece(0.2,x)
sage: f2 = partial(piece,0.2)
sage: from sage.ext.fast_eval import fast_float
sage: subf1 = fast_float(c*x^2, 'c', 'x')
sage: subf2 = fast_float(1/x-c, 'c', 'x')
sage: def piece_ff(c,x):
....:     if x<float(1.0):
....:         return subf1(c,x)
....:     else:
....:         return subf2(c,x)
....:
sage: f1_ff = lambda x: piece_ff(0.2,x)
sage: f2_ff = partial(piece_ff, float(0.2))
sage: f1_ff = lambda x: piece_ff(float(0.2),x)
sage: timeit('[f1_ff(i) for i in range(-10r,10r)]')
625 loops, best of 3: 506 µs per loop
sage: timeit('[f2_ff(i) for i in range(-10r,10r)]')
625 loops, best of 3: 287 µs per loop
sage: timeit('[f1(i) for i in range(-10r,10r)]')
625 loops, best of 3: 904 µs per loop
sage: timeit('[f2(i) for i in range(-10r,10r)]')
625 loops, best of 3: 707 µs per loop



Jason


--~--~---------~--~----~------------~-------~--~----~
To post to this group, send email to sage-support@googlegroups.com
To unsubscribe from this group, send email to [EMAIL PROTECTED]
For more options, visit this group at 
http://groups.google.com/group/sage-support
URLs: http://www.sagemath.org
-~----------~----~----~----~------~----~------~--~---

Reply via email to