Ticket #2697 (new enhancement)

Opened 10 months ago

Last modified 2 weeks ago

[with patch, needs review] allow integration without explicit variable declaration

Reported by: was Assigned to: kcrisman
Priority: major Milestone: sage-3.4
Component: calculus Keywords:
Cc:

Description

This is right:

sage: integrate(x, x,-1,1)
0

This error message (which is because I forgot to give the variable of integration) is completely broken. The "raise err" line in the source code should be just "raise", i.e., delete err, which makes no sense. Or? Anyway, this is just wrong as is.

sage: integrate(x, -1,1)
---------------------------------------------------------------------------
<type 'exceptions.ValueError'>            Traceback (most recent call last)

/Users/was/<ipython console> in <module>()

/Users/was/build/sage-2.10.4/local/lib/python2.5/site-packages/sage/calculus/functional.py in integral(f, *args, **kwds)
    255         return f.integral(*args, **kwds)
    256     except ValueError, err:
--> 257         raise err
    258     except AttributeError:
    259         pass

<type 'exceptions.ValueError'>: variable name is not a valid Python identifier

Attachments

int_without_var.patch (1.9 kB) - added by kcrisman on 10/16/2008 07:55:07 PM.
Apply this patch to 3.1.4 to integrate without variables (sometimes)
int_without_var-final.patch (3.6 kB) - added by kcrisman on 10/31/2008 08:20:21 PM.
Based on 3.2.alpha0
2697-integrate-without-var.patch (2.8 kB) - added by robertwb on 12/19/2008 06:53:16 PM.
trac_2697.patch (4.1 kB) - added by kcrisman on 12/26/2008 08:24:57 PM.
Based on 3.2.2

Change History

04/08/2008 07:11:28 PM changed by mabshoff

I am not sure that the suggested fix does solve the problem:

sage: integrate(x, -1,1)
---------------------------------------------------------------------------
<type 'exceptions.ValueError'>            Traceback (most recent call last)

/scratch/mabshoff/release-cycle/sage-3.0.alpha3/<ipython console> in <module>()

/scratch/mabshoff/release-cycle/sage-3.0.alpha3/local/lib/python2.5/site-packages/sage/calculus/functional.py in integral(f, *args, **kwds)
    253     """
    254     try:
--> 255         return f.integral(*args, **kwds)
    256     except ValueError, err:
    257         raise

/scratch/mabshoff/release-cycle/sage-3.0.alpha3/local/lib/python2.5/site-packages/sage/calculus/calculus.py in integral(self, v, a, b)
   2475
   2476         if not isinstance(v, SymbolicVariable):
-> 2477             v = var(repr(v))
   2478             #raise TypeError, 'must integrate with respect to a variable'
   2479         if (a is None and (not b is None)) or (b is None and (not a is None)):

/scratch/mabshoff/release-cycle/sage-3.0.alpha3/local/lib/python2.5/site-packages/sage/calculus/calculus.py in var(s, create)
   5238             raise ValueError, "the variable '%s' has not been defined"%var
   5239         pass
-> 5240     v = SymbolicVariable(s)
   5241     _vars[s] = v
   5242     _syms[s] = v

/scratch/mabshoff/release-cycle/sage-3.0.alpha3/local/lib/python2.5/site-packages/sage/calculus/calculus.py in __init__(self, name)
   5072             raise ValueError, "variable name must be nonempty"
   5073         elif not is_python_identifier.match(name):
-> 5074             raise ValueError, "variable name is not a valid Python identifier"
   5075
   5076     def __hash__(self):

<type 'exceptions.ValueError'>: variable name is not a valid Python identifier
sage:

Thoughts?

Cheers,

Michael

10/16/2008 07:55:07 PM changed by kcrisman

  • attachment int_without_var.patch added.

Apply this patch to 3.1.4 to integrate without variables (sometimes)

10/16/2008 08:02:38 PM changed by kcrisman

  • type changed from defect to enhancement.
  • summary changed from stupid bug in integrate (easy to fix) to [with patch, needs review] allow integration without explicit variable declaration.

These should now work:

sage: integrate(x, -1,1)
0
sage: integrate(sin(x),0,pi)
2

Sadly, because I don't know enough about Maxima to get it to accept the default variable, we still get this joke one might make in freshman calculus:

sage: integrate(sin,0,pi) 
pi*sin 

(follow-up: ↓ 4 ) 10/30/2008 02:31:47 PM changed by robertwb

  • summary changed from [with patch, needs review] allow integration without explicit variable declaration to [with patch, negative review] allow integration without explicit variable declaration.

I'm getting

sage: integrate(sin(x), pi, 2*pi)
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
  File "/Users/robert/sage/sage-3.1.3/local/lib/python2.5/site-packages/sage/calculus/functional.py", line 254, in integral
    return f.integral(*args, **kwds)
  File "/Users/robert/sage/current/local/lib/python2.5/site-packages/sage/calculus/calculus.py", line 2586, in integral
    raise TypeError, 'only one endpoint given'
TypeError: only one endpoint given

Rather than catching the error that, say, 0 is not a valid variable name, perhaps one should look at the number of variables passed to determine how to integrate. E.g.

sage: integrate(sin(x))               # 0 args, implicit indefinite
cos(x)
sage: integrate(sin(x), y)            # 1 arg, explicit indefinite
sin(x)*y
sage: integrate(sin(x), pi, 2*pi)     # 2 args, implicit definite
-2
sage: integrate(sin(x), y, pi, 2*pi)  # 3 args, explicit definite
pi*sin(x)

(in reply to: ↑ 3 ) 10/31/2008 08:19:53 PM changed by kcrisman

  • owner changed from was to kcrisman.
  • summary changed from [with patch, negative review] allow integration without explicit variable declaration to [with patch, needs review] allow integration without explicit variable declaration.

Replying to robertwb:

Posting (final? I hope) version of patch, based on 3.2.alpha0. Passed doctests for calculus.py once, all other times it timed out for me, but I do not believe it changes pre-existing correct behavior.

I'm getting {{{ sage: integrate(sin(x), pi, 2*pi) ------------------------------------------------------------ Traceback (most recent call last): File "<ipython console>", line 1, in <module> File "/Users/robert/sage/sage-3.1.3/local/lib/python2.5/site-packages/sage/calculus/functional.py", line 254, in integral return f.integral(*args, **kwds) File "/Users/robert/sage/current/local/lib/python2.5/site-packages/sage/calculus/calculus.py", line 2586, in integral raise TypeError?, 'only one endpoint given' TypeError?: only one endpoint given }}}

Turns out that this actually comes from the original code, where the second item was turned into a variable in case someone used some already-in-use identifier for the variable; the problem was that it turned things like e and pi into variables.

Rather than catching the error that, say, 0 is not a valid variable name, perhaps one should look at the number of variables passed to determine how to integrate. E.g. {{{ sage: integrate(sin(x)) # 0 args, implicit indefinite cos(x) sage: integrate(sin(x), y) # 1 arg, explicit indefinite sin(x)*y sage: integrate(sin(x), pi, 2*pi) # 2 args, implicit definite -2 sage: integrate(sin(x), y, pi, 2*pi) # 3 args, explicit definite pi*sin(x) }}}

Good idea! In the end, though, it was easier for me to just jury-rig the code as is. When I make my own functions I try to do that sort of planning, but I don't feel confident enough (or have enough time) to completely change the way this type of code works. Hopefully my final solution is still pretty good, though; it does all of the above, except you will have to declare y beforehand (I couldn't find a way around that), and the first integral is -cos(x) :)

As a bonus, I was finally able to figure out how to do this, which now works:

sage: integrate(sin,0,pi)
2

That alone is worth it for me.

10/31/2008 08:20:21 PM changed by kcrisman

  • attachment int_without_var-final.patch added.

Based on 3.2.alpha0

10/31/2008 08:23:07 PM changed by kcrisman

  • milestone changed from sage-3.2.1 to sage-3.2.

10/31/2008 08:40:20 PM changed by robertwb

Hmm... now I get

sage: var('x,a,b')
(x, a, b)
sage: integral(x^2, a, b)
------------------------------------------------------------
Traceback (most recent call last):
  File "<ipython console>", line 1, in <module>
  File "/Users/robert/sage/current/local/lib/python2.5/site-packages/sage/misc/functional.py", line 418, in integral
    return x.integral(*args, **kwds)
  File "/Users/robert/sage/current/local/lib/python2.5/site-packages/sage/calculus/calculus.py", line 2594, in integral
    raise TypeError, 'only one endpoint given'
TypeError: only one endpoint given

where I'd expect (b^3 - a^3)/3.

11/03/2008 06:43:27 PM changed by kcrisman

  • summary changed from [with patch, needs review] allow integration without explicit variable declaration to [with patch, do not review] allow integration without explicit variable declaration.
  • milestone changed from sage-3.2 to sage-3.2.1.

Okay, fair enough. My philosophy was to improve what was there - all the examples you gave were errors before, too - but I agree that having a very robust function is the best goal long term. However, it may take a little longer to get there. Thanks for the careful reading of the code to find these (so far) non-examples; if we can get all of them it will make integrate very intuitive indeed.

12/19/2008 06:52:59 PM changed by robertwb

  • summary changed from [with patch, do not review] allow integration without explicit variable declaration to [with patch, needs review] allow integration without explicit variable declaration.

I've attached a new patch that resolves this issue. It should be more robust, as it figures out to do first rather than catching errors.

12/19/2008 06:53:16 PM changed by robertwb

  • attachment 2697-integrate-without-var.patch added.

12/21/2008 01:58:44 PM changed by kcrisman

I don't have a chance to review this yet (tomorrow?) but at least want to point out that the other day I noticed that the functionality did also not work for CallableSymbolicExpression? (e.g. lines 5779 or so the integral() method), which seems to have an even more primitive version of the same code. E.g., to try the original example for this ticket:

sage: f(x)=x
sage: f
x |--> x
sage: type(f)
<class 'sage.calculus.calculus.CallableSymbolicExpression'>
sage: integrate(f,-1,1)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<snip>
sage: f.integral(-1,1)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<snip>

But this does work, so I think one would really have to fix the CallableSymbolicVariable? piece:

sage: f.integral(x,-1,1)
0
sage: integral(f,x,-1,1)
0

Thanks for working on this - I knew it would be impossible for me to get to it until after the semester, and that proved to be true.

12/23/2008 10:49:46 AM changed by robertwb

Thanks for starting to look at this. I think integrating symbolic equations should be a separate ticket.

12/26/2008 08:24:57 PM changed by kcrisman

  • attachment trac_2697.patch added.

Based on 3.2.2

12/26/2008 08:36:06 PM changed by kcrisman

Okay, I like your patch. I do think that there should be support for

sage: f(x)=x
sage: integrate(f,-1,1)
0

I wasn't suggesting integrating a symbolic equation, just that the same behavior results for

sage: integrate(f,-1,1)
0
sage: integrate(x,-1,1)
0

because I don't think most newbie Sage users will get the difference between f(x)=x and f=x, for instance. Anyway, the latest patch applies the appropriate parts of your patch to CallableSymbolicExpression? as well; there needs to be less checking because of the different return expected, e.g. indefinite integral is already handled by the previous code (still returning a CallableSymbolicExpression?, though).

Unfortunately, calculus.py always times out for me when I test it. I tried to check that I did not change any existing behavior but hopefully you (or someone else) can check this.

Otherwise positive review!