Burcin Erocal wrote: > Hi Jason, > > On Thu, 12 Nov 2009 12:30:11 -0600 > Jason Grout <jason-s...@creativetrax.com> wrote: > >> It would be nice if we could do something like: >> >> sage: f(x,0)=e^x >> >> sage: f(x,t)=x*t >> >> >> or >> >> sage: f(0)=0 >> sage: f(x)=sin(x)/x >> >> Is there an elegant way to have multiple definitions like this in >> pynac, or definitions with specific conditions on the arguments? > > You can do this: > > sage: def eval_f(x): > ....: if x.is_zero(): > ....: return 0 > ....: return sin(x)/x > ....: > sage: f = function('f',nargs=1, eval_func=eval_f) > sage: f(0) > 0 > sage: f(x) > sin(x)/x > > > I like the fact that the conditions and comparison order is explicit. >
Thanks for this example. I've been trying to play with it. I have a couple of comments: 1. It seems that once I run the above code, it is impossible for me to redefine the function f. For example, running the following gives an error the indicates that the first definition of f is still around: sage: def eval_f(x): ... if x.is_zero(): ... return 0 ... return sin(x)/x ... sage: f = function('f',nargs=1, eval_func=eval_f) sage: def eval_f(x,t): ... if x<0: ... return 0 ... else: ... return sin(x+t)/x ... sage: f=function('f', nargs=2,eval_func=eval_f) sage: f(-1,1) Traceback (most recent call last): ... TypeError: Symbolic function f takes exactly 1 arguments (2 given) 2. The above technique lets me do this: def eval_f(x,t): if x<0: return 0 else: return sin(x+t)/x f=function('f', nargs=2,eval_func=eval_f) plot(lambda x: f(x,x),(t,-10,10)) and get a nice piecewise defined function plot. However, this does *not* work: plot(f(t,t),(t,-10,10)) I understand why it doesn't work---x<0 is false, so an expression is returned and then values are substituted into f. I could think of this as being two different problems: the first argument of plot is evaluated, where I wish there was a hold=True argument I could pass to f to keep it from being evaluated (there's another vote for this feature!). On the other hand, the problem could also be seen as the comparison x<0 is completely useless if x is a symbolic variable. I shouldn't even be trying to have a case statement if we have a symbolic variable input! So I did the following, which seemed to work, but also seemed a bit kludgy: from functools import wraps def eval_if_numeric(f): @wraps(f) def my_f(*args,**kwds): try: all(CC(a) for a in args) except TypeError: return None return f(*args,**kwds) return my_f @eval_if_numeric def eval_f(x,t,**kwds): if x<=0: return 0 else: return sin(x+t)/x f=function('f', nargs=2,eval_func=eval_f) plot(f(t,t),(t,-10,10)) Also, I just discovered that the following does work: def eval_f(x,t,*args,**kwds): if x<0: return 0 else: return n(sin(x+t)/x) f=function('f', nargs=2,evalf_func=eval_f) plot(f(t,t),(t,-10,10)) but then f(1,1) just returns f(1,1), not sin(2). What if we made it so that there was (yet another?) eval function that guaranteed that inputs would not be symbolic expressions, but numbers---basically what my decorator above was doing. Using this idea, then: def eval_f(x,t,*args,**kwds): if x<0: return 0 else: return sin(x+t)/x f=function('f', nargs=2,eval_num_func=eval_f) would have the following properties: sage: f(x,1) f(x,1) sage: f(1,1) sin(2) sage: f(-1,t) f(-1,t) sage: f(-1,1) 0 3. The documentation to "function" is horribly out of date, at least regarding the parameters you bring up in the example above. (Yes, I know, submit a patch...I'm just bringing it up...) > There are subtle changes in pattern matching between different versions > of MMA, and this leads to really (really, really!) hard to track bugs in > code written this way. I've heard many people (not all from the same > institute :) ) complain about this. Interesting; I didn't know that. I think that is orthogonal to the niceness of a pattern-matching interface to function definition, though. Thanks for all of your work on this! Jason -- Jason Grout -- To post to this group, send an email to sage-devel@googlegroups.com To unsubscribe from this group, send an email to sage-devel-unsubscr...@googlegroups.com For more options, visit this group at http://groups.google.com/group/sage-devel URL: http://www.sagemath.org