Good idea. The ability to generate random expressions is very useful. We should make this more general and add it to sympy/utilities/iterables.py.
I had to make a few modifications to your script. First off, you were testing if integral(function.diff(x)) == function, which has two problems: first, you don't even pass it to simplify(). As I said, the integral will usually not look like the original function. But more importantly, it need not even be true. The function and the integral of the derivative of the function can differer by a constant. Second, it's better to catch NotImplementedError and continue. Third, you should never use from import * outside of the interpreter (i.e., in a script). I know it's lazy, but it's a bad habit to get into. Fourth, I also regular print the original expression, which makes it easier to copy and paste it if it is wrong and I need to debug it. I attached an improved script. Thanks for taking the time to look into this. Aaron Meurer On Aug 19, 2010, at 11:06 AM, Christian Muise wrote: > So it's been about 6 years since I've done calculus, and in fact the only > math I see from day to day is pretty much 100% symbolic. That being said, > I've attached a script that may help, or at least satisfy some curiosity. > It's crude, but simple enough to toy around with and checks that the integral > of the diff is the same as the original (not sure what to do to check this > doesn't require constant factors). Just running it a few times finds > NotImplemented errors, odd looking results, etc. This is about all I can > offer as far as testing the thing goes ;). > > Cheers > > On Thu, Aug 19, 2010 at 12:50 PM, Christian Muise <christian.mu...@gmail.com> > wrote: > Apparently the setup.py is dated: > > cjmu...@haz:~/Projects/sympy$ git diff > diff --git a/setup.py b/setup.py > index bdec104..538904d 100755 > --- a/setup.py > +++ b/setup.py > @@ -71,6 +71,7 @@ > 'sympy.mpmath.matrices', > 'sympy.mpmath.calculus', > 'sympy.polys', > + 'sympy.polys.domains', > 'sympy.printing', > 'sympy.printing.pretty', > 'sympy.series', > cjmu...@haz:~/Projects/sympy$ > > On Thu, Aug 19, 2010 at 12:39 PM, Christian Muise <christian.mu...@gmail.com> > wrote: > I'm having issues with the branch: > > >>> from sympy import * > Traceback (most recent call last): > File "<input>", line 1, in <module> > File "/usr/local/lib/python2.6/dist-packages/sympy/__init__.py", line 24, > in <module> > from polys import * > File "/usr/local/lib/python2.6/dist-packages/sympy/polys/__init__.py", line > 3, in <module> > from polytools import ( > File "/usr/local/lib/python2.6/dist-packages/sympy/polys/polytools.py", > line 66, in <module> > from sympy.polys.domains import FF, QQ > ImportError: No module named domains > >>> > > I guess it's the version I'm using? Python 2.6.5 is installed. > > On Wed, Aug 18, 2010 at 11:43 PM, Aaron S. Meurer <asmeu...@gmail.com> wrote: > So a few words. First, if you just pass it a strictly rational function, it > is nothing new. It will return the exact same result as integrate() because > it uses the exact same function, which is the already existing ratint() > (however, there is a fix in my branch for rational functions with symbolic > coefficients that fail in master). > > To really test this, you need to pass it a function that has exp and/or log > in it. For example, here are some functions that you might try that better > test the algorithm: > > In [2]: risch_integrate(1/(exp(x)**9 + 1), x) > Out[2]: > ⎛ 9⋅x⎞ > log⎝1 + ℯ ⎠ > x - ───────────── > 9 > > (your example with x replaced with exp(x)) > > In [18]: risch_integrate(diff(exp(x)*log(x)/(x + 1), x), x) > Out[18]: > x > ℯ ⋅log(x) > ───────── > 1 + x > > This seems to be a simple example, but observe that our current integrate() > cannot handle it: > > In [19]: integrate(diff(exp(x)*log(x)/(x + 1), x), x) > Out[19]: > ⌠ > ⎮ ⎛ x x x ⎞ > ⎮ ⎜ℯ ⋅log(x) ℯ ⋅log(x) ℯ ⎟ > ⎮ ⎜───────── - ───────── + ─────────⎟ dx > ⎮ ⎜ 1 + x 2 x⋅(1 + x)⎟ > ⎮ ⎝ (1 + x) ⎠ > ⌡ > > Also, it's fun to pass it functions that you know do not have elementary > anti-derivatives, to see if it can verify that fact: > > In [20]: risch_integrate(exp(x**2), x) > Out[20]: > ⌠ > ⎮ ⎛ 2⎞ > ⎮ ⎝x ⎠ > ⎮ ℯ dx > ⌡ > > In [21]: risch_integrate(1/log(x), x) > Out[21]: > ⌠ > ⎮ 1 > ⎮ ────── dx > ⎮ log(x) > ⌡ > > Also, remember what I said about integrating random functions. If you try to > integrate a random function, the chances are pretty good that it will not be > elementary, and even if it is, the result could be quite complicated and it > could take a long time to compute. Much better is to come up with an > expression that is as complex or not complex as you like, then differentiate > it and see if risch_integrate() can give you the original thing back again. > > On Aug 18, 2010, at 9:05 PM, Ondrej Certik wrote: > > > Hi Aaron! > > > > On Thu, Aug 5, 2010 at 2:01 PM, Aaron S. Meurer <asmeu...@gmail.com> wrote: > >> (copied from issue 2010) > >> > >> I have ready in my integration3 branch a prototype risch_integrate() > >> function, that is a user-level function for the full Risch Algorithm I > >> have been implementing this summer. Pull from > >> http://github.com/asmeurer/sympy/tree/integration3 > > > > This is just excellent! > > > > I would like to invite everyone to try this. (Read Aaron's email above > > for things to try and not to try yet.) So here are some tougher cases: > > > > In [1]: risch_integrate(1/(x**8+1), x) > > [hangs] > > This is our old friend expand() again (if you break anything that hangs in > sympy these days, it usually ends up being in expand in the traceback). I am > hoping that Mateusz's continual Poly improvements will make this go away > eventually. > > > > > > > In [4]: cancel(risch_integrate(1/(x**9+1), x).diff(x)) > > Out[4]: > > d ⎛ ⎛ 6 3 ⎞⎞ 3 d ⎛ > > 1 + 3⋅──⎝RootSum⎝531441⋅t + 729⋅t + 1, Λ(t, t⋅log(x + 9⋅t))⎠⎠ + 3⋅x > > ⋅──⎝Root > > dx dx > > ────────────────────────────────────────────────────────────────────────────── > > 3 > > 3 + 3⋅x > > > > ⎛ 6 3 ⎞⎞ > > Sum⎝531441⋅t + 729⋅t + 1, Λ(t, t⋅log(x + 9⋅t))⎠⎠ > > > > ────────────────────────────────────────────────── > > > > > > It should be equivalent but it's a bit messy. Maybe we need to > > implement some symbolic manipulation of RootSum(). > > Mateusz should look at this. > > > > > In [18]: risch_integrate(sqrt(1+exp(x)), x) > > NotImplementedError: Couldn't find an elementary transcendental > > extension for (1 + exp(x))**(1/2). Try using a manual extension with > > the extension flag. > > No, and it won't be any time soon. The algorithm I am implementing is only > the transcendental case (no algebraic functions like sqrt). Now, the > algebraic part does exist, but it is much more difficult to implement, and I > won't even start to do it until the transcendental case is finished. If you > get the above error, and you believe that the function is really not > algebraic, please post it here because it could be a bug in my preparser > algorithm, (be aware that you could be wrong, though). > > > > > > > [18] is probably not supported yet. > > > > > > Otherwise it works great. I wasn't able to make it break. > > Well, I know it's possible, because I do it all the time (and then I go and > fix the bug). > > > > > > > Ondrej > > Aaron Meurer > > -- > You received this message because you are subscribed to the Google Groups > "sympy" group. > To post to this group, send email to sy...@googlegroups.com. > To unsubscribe from this group, send email to > sympy+unsubscr...@googlegroups.com. > 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 sy...@googlegroups.com. > To unsubscribe from this group, send email to > sympy+unsubscr...@googlegroups.com. > For more options, visit this group at > http://groups.google.com/group/sympy?hl=en. > <ri.py>
-- You received this message because you are subscribed to the Google Groups "sympy" group. To post to this group, send email to sy...@googlegroups.com. To unsubscribe from this group, send email to sympy+unsubscr...@googlegroups.com. For more options, visit this group at http://groups.google.com/group/sympy?hl=en.
On Aug 19, 2010, at 11:06 AM, Christian Muise wrote: So it's been about 6 years since I've done calculus, and in fact the only math I see from day to day is pretty much 100% symbolic. That being said, I've attached a script that may help, or at least satisfy some curiosity. It's crude, but simple enough to toy around with and checks that the integral of the diff is the same as the original (not sure what to do to check this doesn't require constant factors). Just running it a few times finds NotImplemented errors, odd looking results, etc. This is about all I can offer as far as testing the thing goes ;). |
#! /usr/bin/env python from sympy import (exp, log, risch_integrate, cancel, pretty_print, Symbol, diff) import random x = Symbol('x') unops = [exp, log, lambda x: -x] binops = [lambda x,y: x+y, lambda x,y: x-y, lambda x,y: x*y, lambda x,y: x/y] TRIALS = 5 def build_func(starting_vars = 2, starting_nums = 4, prob_unary = 0.5): parts = [x] * starting_vars for i in range(starting_nums): parts.append(random.randrange(1,10)) #print "Working with the following building blocks: %s" % str(parts) while len(parts) > 1: if random.random() < prob_unary: index = random.randrange(0,len(parts)) parts[index] = random.choice(unops)(parts[index]) else: random.shuffle(parts) parts.append(random.choice(binops)(parts.pop(), parts.pop())) return parts[0] for i in range(TRIALS): eq = build_func() print "\n\n------------------------------\nTesting the following equation:\n" print eq pretty_print(eq) print "\n\nDiff:\n" d = diff(eq, x) pretty_print(d) print "\n\nIntegral of Diff:\n" try: res = risch_integrate(d, x) except NotImplementedError, detail: print "\nNotImplemented (%s)" % detail else: pretty_print(res) print "\nDifference (should be constant): %s" % str(cancel(res - eq)) print "\nDiff difference (should be 0): %s" % str(cancel(diff(res, x) - d)) print "------------------------------"