I find this very encouraging. Some thoughts:
1. Rather than accumulate a list of transformations is it possible to accumulate a tree? Rather than infer which transformations were sub-transformations of others by looking for sub-expressions I wonder if we can collect this information directly. 2. What other meta-data is available? Would any of this be valuable for future presentation / human analysis? In particular as you extend to other methods (you could try all of `_eval_*`) 3. Automatic evaluation is another issue in SymPy that we would like to work on. This project may overlap with that issue a bit. 4. *Perhaps there is some flag somewhere to recursively disable simplifications - *see https://github.com/sympy/sympy/pull/2917 5. *I suspect another possible approach would be to somehow modify the code **so that it first outputs purely symbolic, not actually evaluated or applied, differentiation **nodes, displays them, and then proceeds to evaluate them. -- * Yes, it would be very nice to have explicit stages before and after evaluation. More or less SymPy does do this, you just need to track more functions than `_eval_derivative`. Unfortunately we don't do this very consistently, but this could change. If you want a somewhat clean example, and if you're familiar with linear algebra, then I recommend trying your system on the matrix expression module and the `__new__`, `doit`, and `_eval_foo` methods (note that sympy matrix expressions is different from normal sympy matrices). I'm personally biased towards this module, but I do think that it is more self-consistent than much of SymPy. I often use it as a test-bed for projects like this. >>> n = Symbol('n') >>> X = MatrixSymbol('X', n, n) >>> Y = MatrixSymbol('Y', n, n) >>> (X + X + Y).T 2*X' + Y' 6. How could this functionality be useful to people? What are some applications? Best, -Matt On Sun, Mar 2, 2014 at 8:48 AM, <[email protected]> wrote: > Hello > > I've made a little progress today. > > I made a little program ( > https://raw.github.com/bl0ckeduser/sympy/master/test.py) that tracks > the stack frames of all calls to _eval_derivative and prints out their > inputs and outputs, > as the Wiki suggested. > > The output for that exact task looks something like this: > > Expression : cos(log(sqrt(a)) > Differentiating w.r.t. a: > d/d( a ) [ a ] = 1 > d/d( a ) [ sqrt(a) ] = 1/(2*sqrt(a)) > d/d( a ) [ log(sqrt(a)) ] = 1/(2*a) > d/d( a ) [ cos(log(sqrt(a))) ] = -sin(log(sqrt(a)))/(2*a) > > This does what the wiki suggests, but it is not exactly clear > how consecutive steps relate to each other. Of course, this is not > the exact desired behaviour, as found in programs like Wolfram. > > So I took things further by writing a little loop that looks for exact > substitutions between steps to try to write a full "step-by-step" solution > showing the original full expression as it evolves after every call to the > derivative routine. > Unfortunately this doesn't work very well for many expressions because > there is some kind of simplification code being called somewhere that kills > exact substitutions, for example [ 1/(2*a) ] in one step gets multiplied > by [ -sin(log(sqrt(a))) ] in the next step, but it is not possible to see > the exact earlier node [ 1/(2*a) ] in the resulting expression [ > -sin(log(sqrt(a)))/(2*a) ]. > Perhaps there is some flag somewhere to recursively disable > simplifications ? > > Below is one case (with output slightly reformatted from my test program) > where this hacky loop did work relatively well: > > D(cos(log(a**5) + sin(a))**2, a) > = -2 * D(log(a**5) + sin(a), a) * sin(log(a**5) + sin(a)) * > cos(log(a**5) + sin(a)) > = -2 * ( D(log(a**5), a) + D(sin(a), a) ) * sin(log(a**5) + sin(a)) > * cos(log(a**5) + sin(a)) > = -2*(cos(a) + 5/a) * sin(log(a**5) + sin(a)) * cos(log(a**5) + sin(a)) > > A combined chain and power rule is somewhat visible in the first two > lines, > and a sum rule / linear distribution of differentiation is visible the > second. > In the last step, cos(a) and log(a**5) are both differentiated. > > I suspect another possible approach would be to somehow modify the code > so that it first outputs purely symbolic, not actually evaluated or > applied, differentiation > nodes, displays them, and then proceeds to evaluate them. > > I'm still quite unsure whether the overall task is approachable or not. > > Best, > > Bl0ckeduser > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To unsubscribe from this group and stop receiving emails from it, send an > email to [email protected]. > To post to this group, send email to [email protected]. > Visit this group at http://groups.google.com/group/sympy. > To view this discussion on the web visit > https://groups.google.com/d/msgid/sympy/7061ccce-d9a8-46c3-b52d-87bc3de0acdb%40googlegroups.com > . > > For more options, visit https://groups.google.com/groups/opt_out. > -- You received this message because you are subscribed to the Google Groups "sympy" group. To unsubscribe from this group and stop receiving emails from it, send an email to [email protected]. To post to this group, send email to [email protected]. Visit this group at http://groups.google.com/group/sympy. To view this discussion on the web visit https://groups.google.com/d/msgid/sympy/CAJ8oX-F%3D-iPig81P-vzuW_BaqLn3t-faBEWPHKbAAJWX1mnGXw%40mail.gmail.com. For more options, visit https://groups.google.com/groups/opt_out.
