Le lundi 06 juin 2011 à 19:32 -0700, Matthew Rocklin a écrit : > So in each elementary SymPy function, call it foo, under the eval > method I could add a test to see if the argument has an attribute, > _eval_foo and if so call it?
That doesn't sound like a good idea, there are just too many functions for this to be practical. The object should have only one method, acting like some kind of __rcall__, i.e. foo(X) calls X.__rcall__(foo). The method could perhaps just return a wrapper around the ordinary, not random-aware, version of foo(X). The wrapper would handle the random stuff and let foo handle the function stuff. > > On Mon, Jun 6, 2011 at 7:09 PM, Aaron Meurer <[email protected]> > wrote: > On Mon, Jun 6, 2011 at 7:19 PM, Matthew Rocklin > <[email protected]> wrote: > >> > In an ideal world the operand (in this case the random > variable X) would > >> > be > >> > able to take control. This is the case for some functions > like abs which > >> > just call the object’s __abs__ method. I can’t find any > evidence that > >> > this > >> > is possible generally in the Python language although I’d > be thrilled to > >> > find that I was incorrect. > >> > >> I'm not sure what you mean by "in the Python language." > For this to > >> work, it would have to be implemented in SymPy. So, for > example, you > >> would have to make sin(x) call x._eval_sin() or something > like that. > >> Quite a few functions in SymPy, like diff(), already do > have a design > >> like this. You would mainly just have to add it to > Function. > > > > When Python sees fn(var) it talks to fn first and doesn't > talk to var. A fun > > exception that I like are operators like __radd__ . When > you call a+b it > > first calls a.__add__(b). If that raises a > NotImplementedError it then calls > > b.__radd__(a). This is how Matrices allow for syntactically > clean scalar > > operations like 5*eye(3) regardless of which side of the > operator the matrix > > is on. This is the sort of behavior I would like. sin(X) > currently throws an > > error, It'd be cool if X could pick that up and take things > over. I don't > > think this is possible in Python though other than the > operator case > > discussed above. I brought this up hoping that someone would > tell me I was > > wrong. > > > This is exactly what I'm suggesting with _eval_sin(). sin() > is a > SymPy function (actually, a class), so of course it can do > whatever > you want. > > Aaron Meurer > > > >> > >> > To achieve minimal disruption of the core I could always > do something > >> > like > >> > X.applyfunc(sin) but this seems unpleasant to write. I > think that > >> > matrices > >> > use this solution. Another thought is to have elementary > sympy > >> > functions > >> > check for an applyfunc method of their arguments and, if > it exists, to > >> > use > >> > it. This would solve my problem and possibly be useful > generally. > >> > >> Another option would be to create your own sin() class, > which would be > >> a RandomVariable. I'm not entirely sure what sorts of > things f(X) > >> would do, where f is some SymPy function and X is a > RandomVariable, so > >> I can't really say what the best design is. For example, > does it make > >> sense to do f(X) for any function f or just certain ones > (like sin())? > >> Do you need sin(X) to act like sin(x) in any way (for > example, should > >> diff(sin(X), X) work)? These are the sorts of questions > whose answers > >> will show what the best design for you is. > > > > What needs to happen in the common case: > > For a continuous random variable X, described by PDF, p(x), > the random > > variable Y = f(X) is described by the pdf > > q(y) = p(f^-1(y)) * | d f^-1(y) / dy | > > This is an annoying but purely symbolic operation that is > often (but not > > always) doable. This is what has to happen when you call Y = > f(X) for simple > > f. The function is effectively just passed into an > expression contained > > within X. If f is sufficiently complex so that this > calculation fails then > > I'll probably just keep things as expressions like sin(X) > for later > > sampling. I think that calling sin(X) should not compute the distribution. If you do it only when it's explicitly requested, you'll avoid unnecessary calculations (stupid example: covariance(Y, sin(cos(X) + exp(X))). There are certainly many interesting things you can do without ever knowing the symbolic form of the distribution, like Monte-Carlo integrals, ... > > I hadn't thought much about the other aspects of what SymPy > functions can do > > (like derivatives) and I'll need to chew on this for a > while. If it's not > > possible to evaluate sin(X) then the expression will stay > something like > > sin(X) (or some variant) just like how sin objects stick > around now if the > > argument doesn't support easy evaluation. Mainly I'm just > trying to > > make redirections of the evaluate part of sin (and all other > sympy > > functions) possible. > > If I can do this from within the function then that's ideal > (for me). If it > > ends up being too invasive then I'll do something like what > you suggest, > > creating my own sin function or creating something that > turns a general > > function into a random-friendly function. > > I'll probably end up making some general form of this anyway > so that > > non-SymPy user-defined functions can be decorated. An > interesting case is > > like writing the value of a random variable to file. This > should be a > > "random action" or some such thing. > >> > >> P.S., I vaguely remember discussing this, or something like > this, > >> already. Did we discuss this prior to your acceptance into > GSoC? That kind of idea must have already come up in the context of quantum physics, tensors or matrices. The problems are basically the same there. > > I've written this down a couple of times on various SymPy > application/wiki > > documents but I don't have any specific memory of discussing > it with anyone > > other than briefly with my mentor. My memory however is that > of a five year > > old's so this definitely could have happened. > > > > > > -- > > You received this message because you are subscribed to the > Google Groups > > "sympy" group. > > 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/sympy?hl=en. > > > > -- > You received this message because you are subscribed to the > Google Groups "sympy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to sympy > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > > > > > > -- > You received this message because you are subscribed to the Google > Groups "sympy" group. > To post to this group, send email to [email protected]. > To unsubscribe from this group, send email to sympy > [email protected]. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. -- You received this message because you are subscribed to the Google Groups "sympy" group. 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/sympy?hl=en.
