sagemath / sage

Main repository of SageMath
https://www.sagemath.org
Other
1.41k stars 474 forks source link

wrong answers or crash for integrals involving real_part #33664

Open DaveWitteMorris opened 2 years ago

DaveWitteMorris commented 2 years ago

As reported in this sage devel thread, integrate can give wrong answers (or crash) when an integral involves real_part or imag_part. Here is a simple example:

sage: c = var("c")
sage: assume(c, "complex")
sage: integrate(real_part(c), (x, 0, 1))                      # wrong answer
c
sage: integrate(imag_part(c), (x, 0, 1))                      # wrong answer
0
sage: integrate(real_part(c), (x, 0, 1), algorithm="sympy")   # correct
real_part(c)
sage: integrate(imag_part(c), (x, 0, 1), algorithm="sympy")   # correct
imag_part(c)
sage: integrate(real_part(c), (x, 0, 1), algorithm="giac")    # wrong answer
c
sage: integrate(imag_part(c), (x, 0, 1), algorithm="giac")    # wrong answer
0
sage: integrate(real_part(c), (x, 0, 1), algorithm="maxima")  # crash
---------------------------------------------------------------------------
RuntimeError                              Traceback (most recent call last)
    ...
~/development/sage94/local/var/lib/sage/venv-python3.9/lib/python3.9/site-packages/sage/interfaces/maxima_lib.py in max_to_sr(expr)
   1702                 op=sage_expr.operator()
   1703             if op in sage_op_dict:
-> 1704                 raise RuntimeError("Encountered operator mismatch in maxima-to-sr translation")
   1705             max_op_dict[op_max]=op
   1706             sage_op_dict[op]=op_max

RuntimeError: Encountered operator mismatch in maxima-to-sr translation

Here is a quick description of what seems to be happening. Sagemath asks maxima to do the integral. Maxima gets the correct answer, but the interface crashes (RuntimeError) when trying to convert the lisp expression to python. Sagemath thinks that maxima was unable to do the integral, so it asks giac to try. Giac gets the wrong answer, because it does not know that the parameter c is complex. This wrong answer is returned by sage.

This ticket will fix the maxima interface, and #33665 will fix the giac interface. The behaviour is reproduced in 9.1 on CoCalc, so these are not new bugs.

Component: interfaces

Keywords: RuntimeError, integration, maxima, real_part

Branch/Commit: public/33664 @ 44aa2db

Issue created by migration from https://trac.sagemath.org/ticket/33664

DaveWitteMorris commented 2 years ago

Branch: public/33664

DaveWitteMorris commented 2 years ago

Description changed:

--- 
+++ 
@@ -31,4 +31,4 @@

 Here is a quick description of what seems to be happening. Sagemath asks maxima to do the integral. Maxima gets the correct answer, but the interface crashes (`RuntimeError`) when trying to convert the lisp expression to python. Sagemath thinks that maxima was unable to do the integral, so it asks giac to try. Giac gets the wrong answer, because it does not know that the parameter `c` is complex. This wrong answer is returned by sage. 

-This ticket will fix the maxima interface, and another ticket will fix the giac interface. The behaviour is reproduced in 9.1 on `CoCalc`, so these are not new bugs.
+This ticket will fix the maxima interface, and #33665 will fix the giac interface. The behaviour is reproduced in 9.1 on `CoCalc`, so these are not new bugs.
DaveWitteMorris commented 2 years ago

Commit: 44aa2db

DaveWitteMorris commented 2 years ago
comment:2

Here is a more detailed description of the maxima problem. I know very little about lisp/maxima, but there seems to be confusion between two lisp variables <ecl $realpart> and <ecl $%realpart>. (I think <ecl $realpart> is the maxima variable/function REALPART, but I don't know why <ecl $%realpart> shows up.) Apparently, there is some kind of incompatibility between sr_to_max and max_to_sr.

At the time the RuntimeError exception is raised, op_max is %REALPART (which I think is the same as <ECL: $%REALPART>) and max_op_dict contains the entry <ECL: $REALPART>: real_part. Since op_max is not in the dictionary, sagemath thinks it should add the entry real_part: <ECL: $%REALPART> to the reverse dictionary sage_op_dict. However, this conflicts with the entry real_part: <ECL: $REALPART> that is already in sage_op_dict, so a RuntimeError is raised.

The maxima problem can be eliminated by changing maxima='realpart' to maxima='%realpart' in

GinacFunction.__init__(self, "real_part",
                               conversions=dict(maxima='realpart',
                                                 sympy='re',
                                                 giac='re'),
                                alt_name="real")

in the file src/sage/functions/other.py, and also making a similar change for imagpart. After these edits:

sage: c = var("c")
sage: assume(c, "complex")
sage: integrate(real_part(c), (x, 0, 1))
real_part(c)
sage: integrate(imag_part(c), (x, 0, 1))
imag_part(c)
sage: integrate(real_part(c), (x, 0, 1), algorithm="maxima")
real_part(c)
sage: integrate(imag_part(c), (x, 0, 1), algorithm="maxima")
imag_part(c)

However, this is not the correct solution, because it causes doctest failures:

**********************************************************************
File "src/sage/functions/other.py", line 1115, in sage.functions.other.Function_real_part.__init__
Failed example:
    real_part(I,hold=True).simplify()
Expected:
    0
Got:
    realpart(I)
**********************************************************************
File "src/sage/functions/other.py", line 1209, in sage.functions.other.Function_imag_part.__init__
Failed example:
    imag_part(I,hold=True).simplify()
Expected:
    1
Got:
    imagpart(I)
**********************************************************************
File "src/sage/calculus/wester.py", line 400, in sage.calculus.wester
Failed example:
    f.simplify()
Expected:
    0
Got:
    x^(1/n)*y^(1/n) - (x*y)^(1/n)
**********************************************************************

New commits:

6ef5831maxima %imagpart instead of imagpart
44aa2dbmaxima %realpart instead of realpart